关于Kuix的窗口刷新机制

 

    这几天都在看Kuix的源代码,了解它的消息处理机制,事件处理,窗口刷新,内部线程处理等等,其实Kuix的核心代码作者已经标志的很清楚了,org.kalmeo.kuix.core,widget包可以修改控件的一些表现,要理解框架的话还是应该看core包,尤其是KuixCanvas.我把Kuix分为三个部分,首先是框架的内部处理机制,主要是几个内部处理线程,其次是控件的布局管理,再次是xml和css的文件解析和控件包,一般人都会习惯从后面开始入手,我也是这样开始的.

    要说明Kuix的窗口显示机制,还是先从一个案例入手,这个问题,我的程序中从服务器读取数据后,弹出新的窗口(或者更新当前窗口),服务器连接用线程管理,接收后更新界面,保证主线程不会足赛,这会出现一个很奇怪的现象,有时候刷新的界面会弹不出来,按动任何一个键盘界面才会马上显示,而且这个现象是随机出现的,在实机上出现的频率较高,根据你接收数据的处理效率,处理任务更重出现的效率越高,比如我采用了ssl通道加密后,出现界面"停滞"的几率大大增高.

    首先怀疑是接收处理数据的代码有问题,或者数据有异常,接着做的一个测试排除了代码或者数据问题,我打开一个连接后,不读取服务器的数据,直接打开本地的ui,这一现象仍然出现,所以判断为线程同步问题,可是对screen,frame加同步锁后,现象更加明显.实际上这个问题出现了一个多月,一直没有彻底解决,知道最近才有时间解读Kuix的窗口弹出机制.

    先从Desktop.setCurrentScreen入手,Desktop可以认为是Kuix所有容器的顶层容器,setCurrentScreen只是替换了当前screen变量,隐藏原来的窗口和菜单,注意,菜单不是screen的一部分,所以screen.remove只是清空窗口,菜单仍然保留

 

	/**
	 * @param screen the screen to set
	 */
	public void setCurrentScreen(Screen screen) {
		if (this.screen == screen) {
			return;
		}
		if (this.screen != null) {
			this.screen.remove();
		}

		// Hide menuPopups
		Menu.hideAllMenuPopups();
	
		// Check transition
		if (screen != null) {
			Transition transition = screen.getTransition();
			if (transition != null && this.screen != null) {
				Kuix.getCanvas().setTransition(transition);
			}
		}
		
		this.screen = screen;
		if (screen != null) {
			super.add(screen);
		}
	}
 

    继续追到Widget.add函数,主要是修改控件链表,触发添加事件等,主要还是invalidate(),触发界面更新

 

	/**
	 * Invalidate the widget's size and position and propagate the information
	 * to its parent. Calling this method will generate a call to the
	 * <code>doLayout()</code> and </code>paint()</code> method on all
	 * invalidated widgets.
	 * 
	 * @param fromWidget the Widget responsible of the invalidation.
	 */
	protected void invalidate(Widget fromWidget) {
		invalidated = true;
		if (parent != null && !parent.invalidated) {
			parent.invalidate(fromWidget);
		}
	}
 

    这个函数似乎看不出什么有用的东西,关键其实在parent.invalidate ,不断的向上递归调用,直到最顶层的Desktop.invalidate,这里有所不同了.调用Kuixcanvas.revalidateNextFrame,所以前面说过Kuixcanvas是相当核心的类,几乎所有的内部线程都在这个类里面.

 

	/* (non-Javadoc)
	 * @see org.kalmeo.kuix.widget.Widget#invalidate(org.kalmeo.kuix.widget.Widget)
	 */
	public void invalidate(Widget fromWidget) {
		super.invalidate(fromWidget);
		Kuix.getCanvas().revalidateNextFrame();
	}
 

    追到下面的函数似乎线索中断了,一直没发现在哪里刷新界面了

 

	/**
	 * Repaint through the Worker task
	 * 
	 * @param x	x coordinate of the repaint region
	 * @param y y coordinate of the repaint region
	 * @param width width of the repaint region
	 * @param height height of the repaint region
	 */
	public void repaintNextFrame(int x, int y, int width, int height) {
		needToRepaint = true;
		repaintRegion.add(x, y, width, height);
	}
 

    实际上关键就在needToRepaint = true;Kuixcanvas有一个内部线程,里面有这个代码,forceRepaint实际上就是刷新界面的函数了.

 

					// Repaint
					if (needToRepaint) {
						forceRepaint();
					}
 

    所以实际上Kuix所有的事件都是通过线程操作的,而不是实时实现.这会有一些延迟,这个延迟就会导致我们用多线程的时候,界面会被随机"冻结",而操作一个任一个按键,都会触发KuixCanvas的消息处理线程,实际上最终触发重绘界面的函数,导致"迟到"的界面重新出现.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值