- 浏览: 147807 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
louisliao:
你好请问你有遇到 repo upload 每次都要求输入用户名 ...
碰到的Git/Repo问题及其解决方法 -
viptmd:
谢谢 lz的解释。。受教了,正在搞dmc
开篇:Java Net & DLNA -
chxiaowu:
楼主,可不可以共享代码啊。 看代码才能理解啊
ActiveObject模式的一个java实现 -
aigyoo:
很有兴趣就是不知道怎么做
jUpload字符集设置 -
enlangs:
学习了。。
开篇:Java Net & DLNA
没搞过swing,也没丰富经验的j2me ui,ios的ui也没折腾过。说实话UI这块看得很辛苦,4天里断断续续的看,至今也没从我想象的高度来认识Android UI的设计细节。
没看明白归没看明白,至少还是有一些问题的。老样子,仔细分析冷冰博文第十二和十三篇: Android GEWS之Android窗口管理之基本架构 和 Android GEWS窗口管理。
下面是我想到的几点:
1. 按照冷冰的分析,为什么在Activity和WindowManager之间会存在一个Session的概念?
先看一张图:
再看Wiki上对Session的解释:
In computer science, in particular networking, a session is a semi-permanent interactive information interchange, also known as a dialogue, a conversation or a meeting, between two or more communicating devices, or between a computer and user (see Login session). A session is set up or established at a certain point in time, and torn down at a later point in time. An established communication session may involve more than one message in each direction. A session is typically, but not always, stateful, meaning that at least one of the communicating parts needs to save information about the session history in order to be able to communicate, as opposed to stateless communication, where the communication consists of independent requests with responses.
所以Session是一种半永久性的互动信息交换(直译,以免翻译错误导致误解)。
再看冷冰的一段话:
Activity建立一个主窗口后,在将主窗口添加到WindowManager时,首先要建立WindowManager代理对象,并打开一个会话(实现IWindowSession AIDL接口),并维持该会话。Activity将通过该会话与WindowManager建立联系,这个Session是C/S体系的基础,Client通过WindowSession将window加入到Window Manager中。
由此看来,C/S结构中,C与S不是能直接通信的(至少在当前场景下),所以Session就像一个中间件,连接一个Activity与WindowManager,使两者可以进行通讯(互动信息的交换)。在J2EE中,我所见到的Login Session也差不多是这样,每个客户端(Browser)和服务器(Server,Server就像这里的WindowManager,单例的)都存在一个维护通信现场和提供通信结构的session,当客户端的浏览器退出或者网页被关闭或者用户主动logout,那么session manager会立即或在未来某个时间关掉这个这个session(可以依据的一些session过期特征,例如过期时间)。
为了证明Session的交换特性,我试图找到Android IWindowSession这个interface的源文件,可惜没找到,只能从class文件来大概了解一下:
// Method descriptor #10 (Landroid/view/IWindow;Landroid/view/WindowManager$LayoutParams;ILandroid/graphics/Rect;Landroid/view/InputChannel;)I
public abstract int add(android.view.IWindow arg0, android.view.WindowManager.LayoutParams arg1, int arg2, android.graphics.Rect arg3, android.view.InputChannel arg4) throws android.os.RemoteException;
// Method descriptor #16 (Landroid/view/IWindow;)V
public abstract void remove(android.view.IWindow arg0) throws android.os.RemoteException;
单从这两个方法就可以看出,IWindowSession接口的确定义了一些交互性的方法(add、remove等)。从设计模式的角度来看,有点适配器(Adapter)的味道(Android中有很明显的Adapter,各种ListView都会用到:它完成了从数据到视图的一个适配)。从应用开发者的角度来看,Session是无需关心的。
补充或者更正:
刚看到IWindowSession实际上是一个AIDL定义的接口,那么就是说,它工作于在linux平台层,而且从
这段代码来看,IWindowSession实际上又是单例的(这跟J2EE中的session和wiki中定义的有些不同)。如果是单例的话,那就意味着这个session是长久的,它至少在android linux启动时被生成,关闭时被销毁,它不会被某个与之相关的WindowManager或者ViewRoot的存亡影响,WM也是单例的,所以它与WM一对一,与VR一对多。因此,android的设计者引入这样一个叫做IWindowSession的东西,并不意味者它就是一个session,也许它只有一些特征相似而已(说实在的,这里比较复杂了,我的小脑瓜实在转不过来,等慢慢理解了再回过头来补充)。
2. View组织结构
UI界面通常是一个树形结构,Android也不例外。那么这棵树的根节点是谁呢?是ViewRoot,这是一个不公开的类。给出两个比较明显的是“根”的特征:
1.继承ViewParent接口
2. ViewParent getParent方法返回null
在ViewRoot之下,冷冰认为有一个DecorView,它在具体的Window中负责组织各个具体View和ViewGroup(就是View或者ViewGroup的实现者)。但是我没找到这个DecorView,但是我也认同这个DecorView的存在,因为两点:
1.ViewRoot实现ViewParent但不实现ViewGroup,所以它不能组织子View元素;
2.ViewRoot持有一个IWindowSession,而这个session正是Activity与外界(WindowManager)交互的桥梁
所以ViewRoot作为根节点它同时肩负着与外界通信的能力,至于组织View结构这类工作就托付给另外一个抽象(DecorView)去做吧。现在来看冷冰的这张图就不难理解了:
ViewRoot并不属于Window空间,因为它更倾向于是Activity对外的桥梁,包括Window也是通过调用ViewRoot的门面方法(方法的实现者其实是IWindowSession的实现者,这点代码中可以印证)而加入到WindowManager中的。
在看ViewParent接口时我注意到一个api:
是的,在UI结构中,focus路径是要关心的一个问题。我忘记了fclient中如何设计解决这个问题的(代码如果能找到的话再补充),在Android中下面的一张图就表述的很清晰:
要找到View22,首先从根部遍历(当然这个根部应该是DecorView,它本身就是一个ViewGroup),找到那个存在focused view的ViewGroup11,然后再在ViewGroup11中找到mFocused(源码中该私有变量的说明原文是这样的:The view contained within this ViewGroup that has or contains focus.) 。
3.事件分发
其实ViewRoot也是一个Handler,它处理或者分发了来自那边(WindowManager)的消息(包括焦点切换、key和pointer事件、die、checkfocus等等很多)。消息在handleMessage内经过switch case语句按照分支进行分发之后,由具体的处理方法去完成剩下的工作。我这里只举一个例子(key event的处理)来帮助自己对这个流程的理解。先看一段代码:
要被处理的消息被包装成KeyEvent并传递进来,首先一个mView会试图处理这个事件,mView又是什么呢,在给mView赋值的setView方法是这么说的:We have one child.那么,这个child就可能就是前面所指的DecorView(但是后来又发现好像不是),所以除过IME(输入法)的事件都给mView去处理(并且如果mView为null,那么该事件会被consume掉),它爱分发分发,爱处理处理,IME的事件呢,则在ViewRoot里面处理,就是第二个if块里面的代码,当然最后deliverKeyEventToViewHierarchy方法也只在处理IME事件时才生效。但实际上在IME之前处理键事件的情况很少,详见dispatchKeyEventPreIme方法的注释.
根据代码我大概得知mView是其实是与当前这个message有直接关系的那个View,所以mView的赋值,应该是由WindowManager这样的设施来负责,因为只有它们才能具体知道用户点击了哪个View。的下面的代码不分析了,很复杂也很多。。总体上感觉,Android事件处理的分发路径就像投石模型(把石头扔到水里,石头一直是下沉的,HTML的事件模型是冒泡),从根节点一直往下,不过这个只是感觉,并不准确(等我发现理解有误时再改正吧,主要是我发现为了举这个例子,我快掉进细节的泥沼了,得赶紧脱身才是,:))。
最后再来看一张图:
结合源码看这段,感觉精妙的很(冷冰大牛啊)。WindowManager、View、ViewRoot、WindowSession等的交互关系也是很准确,只是图略显凌乱,刚开始看不知所云,我也是结合代码看了好久才明白其含义。只是图中没有给清除左下角这些View到底是什么,要不我就比较确定的知道mView了。
4.在Android UI中有没有显示层这样的概念(就像html中的z-index),如果有,那它是怎么处理的?
有一个类似的概念叫做Z-order,在Window Service(注意:Android中I开头的接口通常是aidl接口,它们通常都继承自android.os.IInterface 接口,所以这里指的window service就是实现某个具体aidl接口的远程service),这个order也由该service来维护。这个我还没找到具体的代码来印证。
没看明白归没看明白,至少还是有一些问题的。老样子,仔细分析冷冰博文第十二和十三篇: Android GEWS之Android窗口管理之基本架构 和 Android GEWS窗口管理。
下面是我想到的几点:
1. 按照冷冰的分析,为什么在Activity和WindowManager之间会存在一个Session的概念?
先看一张图:
再看Wiki上对Session的解释:
In computer science, in particular networking, a session is a semi-permanent interactive information interchange, also known as a dialogue, a conversation or a meeting, between two or more communicating devices, or between a computer and user (see Login session). A session is set up or established at a certain point in time, and torn down at a later point in time. An established communication session may involve more than one message in each direction. A session is typically, but not always, stateful, meaning that at least one of the communicating parts needs to save information about the session history in order to be able to communicate, as opposed to stateless communication, where the communication consists of independent requests with responses.
所以Session是一种半永久性的互动信息交换(直译,以免翻译错误导致误解)。
再看冷冰的一段话:
Activity建立一个主窗口后,在将主窗口添加到WindowManager时,首先要建立WindowManager代理对象,并打开一个会话(实现IWindowSession AIDL接口),并维持该会话。Activity将通过该会话与WindowManager建立联系,这个Session是C/S体系的基础,Client通过WindowSession将window加入到Window Manager中。
由此看来,C/S结构中,C与S不是能直接通信的(至少在当前场景下),所以Session就像一个中间件,连接一个Activity与WindowManager,使两者可以进行通讯(互动信息的交换)。在J2EE中,我所见到的Login Session也差不多是这样,每个客户端(Browser)和服务器(Server,Server就像这里的WindowManager,单例的)都存在一个维护通信现场和提供通信结构的session,当客户端的浏览器退出或者网页被关闭或者用户主动logout,那么session manager会立即或在未来某个时间关掉这个这个session(可以依据的一些session过期特征,例如过期时间)。
为了证明Session的交换特性,我试图找到Android IWindowSession这个interface的源文件,可惜没找到,只能从class文件来大概了解一下:
// Method descriptor #10 (Landroid/view/IWindow;Landroid/view/WindowManager$LayoutParams;ILandroid/graphics/Rect;Landroid/view/InputChannel;)I
public abstract int add(android.view.IWindow arg0, android.view.WindowManager.LayoutParams arg1, int arg2, android.graphics.Rect arg3, android.view.InputChannel arg4) throws android.os.RemoteException;
// Method descriptor #16 (Landroid/view/IWindow;)V
public abstract void remove(android.view.IWindow arg0) throws android.os.RemoteException;
单从这两个方法就可以看出,IWindowSession接口的确定义了一些交互性的方法(add、remove等)。从设计模式的角度来看,有点适配器(Adapter)的味道(Android中有很明显的Adapter,各种ListView都会用到:它完成了从数据到视图的一个适配)。从应用开发者的角度来看,Session是无需关心的。
补充或者更正:
刚看到IWindowSession实际上是一个AIDL定义的接口,那么就是说,它工作于在linux平台层,而且从
public static IWindowSession getWindowSession(Looper mainLooper) { synchronized (mStaticInit) { if (!mInitialized) { try { InputMethodManager imm = InputMethodManager.getInstance(mainLooper); sWindowSession = IWindowManager.Stub.asInterface( ServiceManager.getService("window")) .openSession(imm.getClient(), imm.getInputContext()); mInitialized = true; } catch (RemoteException e) { } } return sWindowSession; } }
这段代码来看,IWindowSession实际上又是单例的(这跟J2EE中的session和wiki中定义的有些不同)。如果是单例的话,那就意味着这个session是长久的,它至少在android linux启动时被生成,关闭时被销毁,它不会被某个与之相关的WindowManager或者ViewRoot的存亡影响,WM也是单例的,所以它与WM一对一,与VR一对多。因此,android的设计者引入这样一个叫做IWindowSession的东西,并不意味者它就是一个session,也许它只有一些特征相似而已(说实在的,这里比较复杂了,我的小脑瓜实在转不过来,等慢慢理解了再回过头来补充)。
2. View组织结构
UI界面通常是一个树形结构,Android也不例外。那么这棵树的根节点是谁呢?是ViewRoot,这是一个不公开的类。给出两个比较明显的是“根”的特征:
1.继承ViewParent接口
2. ViewParent getParent方法返回null
在ViewRoot之下,冷冰认为有一个DecorView,它在具体的Window中负责组织各个具体View和ViewGroup(就是View或者ViewGroup的实现者)。但是我没找到这个DecorView,但是我也认同这个DecorView的存在,因为两点:
1.ViewRoot实现ViewParent但不实现ViewGroup,所以它不能组织子View元素;
2.ViewRoot持有一个IWindowSession,而这个session正是Activity与外界(WindowManager)交互的桥梁
所以ViewRoot作为根节点它同时肩负着与外界通信的能力,至于组织View结构这类工作就托付给另外一个抽象(DecorView)去做吧。现在来看冷冰的这张图就不难理解了:
ViewRoot并不属于Window空间,因为它更倾向于是Activity对外的桥梁,包括Window也是通过调用ViewRoot的门面方法(方法的实现者其实是IWindowSession的实现者,这点代码中可以印证)而加入到WindowManager中的。
在看ViewParent接口时我注意到一个api:
/** * Find the nearest view in the specified direction that wants to take focus * * @param v The view that currently has focus * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT */ public View focusSearch(View v, int direction);
是的,在UI结构中,focus路径是要关心的一个问题。我忘记了fclient中如何设计解决这个问题的(代码如果能找到的话再补充),在Android中下面的一张图就表述的很清晰:
要找到View22,首先从根部遍历(当然这个根部应该是DecorView,它本身就是一个ViewGroup),找到那个存在focused view的ViewGroup11,然后再在ViewGroup11中找到mFocused(源码中该私有变量的说明原文是这样的:The view contained within this ViewGroup that has or contains focus.) 。
3.事件分发
其实ViewRoot也是一个Handler,它处理或者分发了来自那边(WindowManager)的消息(包括焦点切换、key和pointer事件、die、checkfocus等等很多)。消息在handleMessage内经过switch case语句按照分支进行分发之后,由具体的处理方法去完成剩下的工作。我这里只举一个例子(key event的处理)来帮助自己对这个流程的理解。先看一段代码:
private void deliverKeyEvent(KeyEvent event, boolean sendDone) { // If mView is null, we just consume the key event because it doesn't // make sense to do anything else with it. boolean handled = mView != null ? mView.dispatchKeyEventPreIme(event) : true; if (handled) { if (sendDone) { finishInputEvent(); } return; } // If it is possible for this window to interact with the input // method window, then we want to first dispatch our key events // to the input method. if (mLastWasImTarget) { InputMethodManager imm = InputMethodManager.peekInstance(); if (imm != null && mView != null) { int seq = enqueuePendingEvent(event, sendDone); if (DEBUG_IMF) Log.v(TAG, "Sending key event to IME: seq=" + seq + " event=" + event); imm.dispatchKeyEvent(mView.getContext(), seq, event, mInputMethodCallback); return; } } deliverKeyEventToViewHierarchy(event, sendDone); }
要被处理的消息被包装成KeyEvent并传递进来,首先一个mView会试图处理这个事件,mView又是什么呢,在给mView赋值的setView方法是这么说的:We have one child.那么,这个child就可能就是前面所指的DecorView(但是后来又发现好像不是),所以除过IME(输入法)的事件都给mView去处理(并且如果mView为null,那么该事件会被consume掉),它爱分发分发,爱处理处理,IME的事件呢,则在ViewRoot里面处理,就是第二个if块里面的代码,当然最后deliverKeyEventToViewHierarchy方法也只在处理IME事件时才生效。但实际上在IME之前处理键事件的情况很少,详见dispatchKeyEventPreIme方法的注释.
根据代码我大概得知mView是其实是与当前这个message有直接关系的那个View,所以mView的赋值,应该是由WindowManager这样的设施来负责,因为只有它们才能具体知道用户点击了哪个View。的下面的代码不分析了,很复杂也很多。。总体上感觉,Android事件处理的分发路径就像投石模型(把石头扔到水里,石头一直是下沉的,HTML的事件模型是冒泡),从根节点一直往下,不过这个只是感觉,并不准确(等我发现理解有误时再改正吧,主要是我发现为了举这个例子,我快掉进细节的泥沼了,得赶紧脱身才是,:))。
最后再来看一张图:
结合源码看这段,感觉精妙的很(冷冰大牛啊)。WindowManager、View、ViewRoot、WindowSession等的交互关系也是很准确,只是图略显凌乱,刚开始看不知所云,我也是结合代码看了好久才明白其含义。只是图中没有给清除左下角这些View到底是什么,要不我就比较确定的知道mView了。
4.在Android UI中有没有显示层这样的概念(就像html中的z-index),如果有,那它是怎么处理的?
有一个类似的概念叫做Z-order,在Window Service(注意:Android中I开头的接口通常是aidl接口,它们通常都继承自android.os.IInterface 接口,所以这里指的window service就是实现某个具体aidl接口的远程service),这个order也由该service来维护。这个我还没找到具体的代码来印证。
发表评论
-
Android客户端数据采集工具包设计
2012-03-06 23:19 7446最近在做一款采集Android应用数据的工具包,类似友盟、fl ... -
[Android游戏开发]基于libgdx的一个简单游戏demo
2012-01-10 14:33 5082最近在利用业余时间自学游戏开发,在看《Begining And ... -
Something about vm gc
2011-10-20 11:06 925It works something like this ... -
图像处理的Dither和Banding
2011-10-12 17:21 13050由于前面的文章涉及到了这两个概念,而我又对图像处理一窍不通,所 ... -
Roman Guy的Android Trick系列文章笔记(三)
2011-10-12 16:08 3263以下所涉及的所有文章都被墙了。。 1.Android ... -
Roman Guy的Android Trick系列文章笔记(二)
2011-10-10 17:43 17295.Speed up your Android UI ... -
Roman Guy的Android Trick系列文章笔记
2011-09-21 15:02 1700Roman Guy是Android Framework ... -
Android开发闲言碎语
2011-08-29 10:52 10301. Android,任何app的生命都是短暂的,所以开发ap ... -
Android开发中的一些经验总结
2011-05-11 10:55 5003计划用这篇文章把目前我在Android领域的一些看到的、用到的 ... -
Android Contacts知识学习
2011-05-10 16:17 0最近接受Contacts这一块的工作,在这里把看到的想到的一些 ... -
Multithreading For Performance
2011-03-17 16:48 0... However, a ListView-specifi ... -
Saving data safely
2011-03-16 22:45 1114我们知道,在Android平台中,保存数据有3种方式:loca ... -
一个代码复用实例
2011-03-14 09:43 1119大概看了一下这篇文章: 新浪微博布局学习——妙用TabHost ... -
Source share: SharedPreferencesCompat.java
2011-03-10 09:39 1732Firstly look at the code: /** ... -
New Gingerbread API: StrictMode阅读笔记
2011-03-09 17:14 1139原文:New Gingerbread API: StrictM ... -
Android Memory Leaks
2011-03-08 23:20 1888前一阵子,有一个bug是关于monkey测试到的memory ... -
Android消息处理框架:Looper,Handler,MessageQueue ...
2011-02-23 22:34 2879看过冷冰的Android核心分析第十一篇:Android GW ... -
Android Service Framework分析
2011-02-23 22:14 4536当我在为fetion client工作 ... -
新的开始
2010-11-01 15:54 817要去做android,很高兴。关注这个平台很久,现在终 ...
相关推荐
Android UI学习.doc
NULL 博文链接:https://choha.iteye.com/blog/1139320
UI学习,电话薄读取,短信读取,主要模仿米聊、口信、微信
项目驱动 紧密结合初学者的学习习惯和认知规律,采用了大量简单而又实用的设计案例分析UI设计的基本理念。 强化技能 以移动UI设计师的核心岗位能力统筹全书的编写,代码设计突出项目开发的实战性与健壮性。 遵守...
《AndroidUI基础教程》是一本Android用户界面设计的基础入门图书。全书从最基础的技术概念开始介绍,深入讨论了UI设计的各项技术,涵盖了为应用程序创建UI的所有内容。本书不仅会告诉读者创建灵活布局的最佳方法,...
Android UI开发经典资料,学习设计Android界面的必备资料
Android UI试练 微信UIDemo 完整的微信的UI,值得下载学习~~
关于Android ui设计的学习资料关于Android ui设计的学习资料
android system UI 学习资料,放到csdn上让大家共同学习,进步。
使用于初学者学习android UI设计和控件使用方法
Android UI组件库,各种好看的组件.rar,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。
Android 开发应用源码 参考学习使用
学习Android时写的demo。备用。
通过这个简洁完整的例子,可以学习到android界面开发中很多的组件,如tabhost,listview,对话框,选项菜单,上下文菜单等等
android用户界面的一些基础知识,有助于大家学习搭建android ui界面
Android UI控件集合,包括Button,TextView,EditView,CheckBox,RadioGroup,Spinner,AutoCompleteTextView,DatePicker,TimePicker,ProgressBar,SeekBar,RatingBar,ImageView,ImageButton,ImageSwicrher,Gallery,...
android tabhost --android UI源码.zip项目安卓应用源码下载android tabhost --android UI源码.zip项目安卓应用源码下载 1.适合学生毕业设计研究参考 2.适合个人学习研究参考 3.适合公司开发项目技术参考
Android UI控件BottomView_Demo。完整的用法Demo,非常好用和经典的控件
对于初学者是比较好的参考。android开发ui学习不可少。花了近1个月的时间写好。