Android的Activity Window和View三者之间的关系解析
2017-08-20 16:55
351 查看
我们知道,Activity是安卓的四大组件之一,负责手机界面的展示和交互。那么他与Window和View是什么关系呢。
下面,我们看一个简单的界面:
它的布局文件如下,很简单:
接着我们用android的sdk所带的工具hierarchyviewer.bat来看看,这个界面到底有哪些元素,截图如下:
从最左边开始看,标号1的地方,有个PhoneWindow和DecorView,可见,PhoneWindow是整个界面的窗口,DecorView是整个界面的根View。标号2是手机的顶部状态栏,标号3是一个id为content的FrameLayout,标号4是一个LinearLayout,这个正是我们在布局文件里设置的元素。那么Android代码里是怎么做的呢。我们看一下我们的Activity代码。
Activity只做了一件事,就是 setContentView,点进去看看源码。
看到这我们发现,Activity把setContentView的工作交给了getwindow()这个方法返回的对象去做,点进getWindow看看,
发现getWindow方法返回一个Window对象,点进window看一下,
发现这是一个抽象类,看看这个类的注释,我来简单翻译一下:
是一个顶级窗口的外观和行为策略的抽象类,他的实现类应该作为顶级view添加到WindowManager中,它提供标准的UI策略,比如背景,标题,区域等。
它的唯一实现类是android.view.PhoneWindow,当你需要一个Window对象的时候,你会实例化它。
由注释看出,Window的唯一实现类是PhoneWindow。下面看一下Activity的attach方法,
发现,在attach方法中对mWindow进行了初始化,即PhoneWindow。下面我们看一下PhoneWindow的源码,我们在FragmeWork中看一下他的源码,源码地址如下:
http://androidxref.com/7.0.0_r1/xref/frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java
看一下它的setContentView方法,
看403行,第一次进来,条件为真,执行installDecor();这个方法代码就不贴了,主要是初始化mContentParent和mDecor,mDecor就是DecorView的实例,是顶级View,他继承自FrameLayout,接着看414看,这句我们应该很熟悉,使用layoutInflater加载我们的xml布局,作为mContentParent的子布局,正好和我们的第一个图的标号3和4对应,mContentParent即是id为content的FrameLayout.
ViewManager有三个方法:
可见WindowManager也是一个接口,他的具体实现类是WindowManagerImpl
源码地址:
http://androidxref.com/7.0.0_r1/xref/frameworks/base/core/java/android/view/WindowManagerImpl.java
可见,他的addView,removeView和updateView都是通过WindowManagerGloabal实现的。WindowManagerGloabal内部最终是通过WindowManagerService来创建Window的。
事件传来之后,调用Window的superDispatchTouchEvent(ev)方法,看一下这个方法:
他又调用mDecor的superDispatchTouchEvent(ev)方法。他的代码地址
http://androidxref.com/7.0.0_r1/xref/frameworks/base/core/java/com/android/internal/policy/DecorView.java
看一下
由于DecorView是继承自FrameLayout的,所以下面进入了事件从ViewGroup向下分发的流程,下面的分发流程大家应该都清楚。
2.Window就是负责界面展示以及交互的职能部门,就相当于Activity的下属,Activity的生命周期方法负责业务的处理;
3.View就是放在Window容器的元素,Window是View的载体,View是Window的具体展示。
下面,我们看一个简单的界面:
它的布局文件如下,很简单:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="hello,world" android:textSize="20sp" android:layout_marginTop="10dp" android:layout_marginLeft="10dp"/> </LinearLayout>
接着我们用android的sdk所带的工具hierarchyviewer.bat来看看,这个界面到底有哪些元素,截图如下:
从最左边开始看,标号1的地方,有个PhoneWindow和DecorView,可见,PhoneWindow是整个界面的窗口,DecorView是整个界面的根View。标号2是手机的顶部状态栏,标号3是一个id为content的FrameLayout,标号4是一个LinearLayout,这个正是我们在布局文件里设置的元素。那么Android代码里是怎么做的呢。我们看一下我们的Activity代码。
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); }
Activity只做了一件事,就是 setContentView,点进去看看源码。
public void setContentView(@LayoutRes int layoutResID) { getWindow().setContentView(layoutResID); initWindowDecorActionBar(); }
看到这我们发现,Activity把setContentView的工作交给了getwindow()这个方法返回的对象去做,点进getWindow看看,
public Window getWindow() { return mWindow; } private Window mWindow;
发现getWindow方法返回一个Window对象,点进window看一下,
/** * Abstract base class for a top-level window look and behavior policy. An * instance of this class should be used as the top-level view added to the * window manager. It provides standard UI policies such as a background, title * area, default key processing, etc. * * <p>The only existing implementation of this abstract class is * android.view.PhoneWindow, which you should instantiate when needing a * Window. */ public abstract class Window
发现这是一个抽象类,看看这个类的注释,我来简单翻译一下:
是一个顶级窗口的外观和行为策略的抽象类,他的实现类应该作为顶级view添加到WindowManager中,它提供标准的UI策略,比如背景,标题,区域等。
它的唯一实现类是android.view.PhoneWindow,当你需要一个Window对象的时候,你会实例化它。
由注释看出,Window的唯一实现类是PhoneWindow。下面看一下Activity的attach方法,
发现,在attach方法中对mWindow进行了初始化,即PhoneWindow。下面我们看一下PhoneWindow的源码,我们在FragmeWork中看一下他的源码,源码地址如下:
http://androidxref.com/7.0.0_r1/xref/frameworks/base/core/java/com/android/internal/policy/PhoneWindow.java
看一下它的setContentView方法,
//其中的两个变量 private DecorView mDecor; ViewGroup mContentParent; @Override 399 public void setContentView(int layoutResID) { 400 // Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window 401 // decor, when theme attributes and the like are crystalized. Do not check the feature 402 // before this happens. 403 if (mContentParent == null) { 404 installDecor(); 405 } else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) { 406 mContentParent.removeAllViews(); 407 } 408 409 if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) { 410 final Scene newScene = Scene.getSceneForLayout(mContentParent, layoutResID, 411 getContext()); 412 transitionTo(newScene); 413 } else { 414 mLayoutInflater.inflate(layoutResID, mContentParent); 415 } 416 mContentParent.requestApplyInsets(); 417 final Callback cb = getCallback(); 418 if (cb != null && !isDestroyed()) { 419 cb.onContentChanged(); 420 } 421 mContentParentExplicitlySet = true; 422 }
看403行,第一次进来,条件为真,执行installDecor();这个方法代码就不贴了,主要是初始化mContentParent和mDecor,mDecor就是DecorView的实例,是顶级View,他继承自FrameLayout,接着看414看,这句我们应该很熟悉,使用layoutInflater加载我们的xml布局,作为mContentParent的子布局,正好和我们的第一个图的标号3和4对应,mContentParent即是id为content的FrameLayout.
Window和View的关系
由此可见,Window是一个界面的窗口(唯一实现类是PhoneWindow),是存放View的容器,也即Window是View的管理者,或者说,View是附着在Window上的。Android中所有的视图都是通过Window来呈现的,比如Activity,Dialog,Toast,他们的视图都是附着在Window上的。比如我们常用的弹出对话框时,把背景变暗,就是通过设置Window的alpha值来实现的。Window的添加、删除和更改是通过WindowManager来实现的。而WindowManager又是继承ViewManager的public interface WindowManager extends ViewManager {
ViewManager有三个方法:
public interface ViewManager 23{ 24 /** 25 * Assign the passed LayoutParams to the passed View and add the view to the window. 26 * <p>Throws {@link android.view.WindowManager.BadTokenException} for certain programming 27 * errors, such as adding a second view to a window without removing the first view. 28 * <p>Throws {@link android.view.WindowManager.InvalidDisplayException} if the window is on a 29 * secondary {@link Display} and the specified display can't be found 30 * (see {@link android.app.Presentation}). 31 * @param view The view to be added to this window. 32 * @param params The LayoutParams to assign to view. 33 */ 34 public void addView(View view, ViewGroup.LayoutParams params); 35 public void updateViewLayout(View view, ViewGroup.LayoutParams params); 36 public void removeView(View view); 37}
可见WindowManager也是一个接口,他的具体实现类是WindowManagerImpl
源码地址:
http://androidxref.com/7.0.0_r1/xref/frameworks/base/core/java/android/view/WindowManagerImpl.java
public final class WindowManagerImpl implements WindowManager {
@Override public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) { applyDefaultToken(params); mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow); } @Override public void updateViewLayout(@NonNull View view, @NonNull ViewGroup.LayoutParams params) { applyDefaultToken(params); mGlobal.updateViewLayout(view, params); } @Override public void removeView(View view) { mGlobal.removeView(view, false); }
可见,他的addView,removeView和updateView都是通过WindowManagerGloabal实现的。WindowManagerGloabal内部最终是通过WindowManagerService来创建Window的。
Activity与Window的关系
我们知道,Activity是向用户展示一个界面,并可以与用户进行交互。通过我们之前的分析,我们知道,Activity内部持有一个Window对象,用来管理View。由此可知,window就像是Activity的一个手下,为Activity管理View,就连事件的分发,也是Activity先发给Window,然后window再向下分发。我们看一下Activity的代码:事件传来之后,调用Window的superDispatchTouchEvent(ev)方法,看一下这个方法:
他又调用mDecor的superDispatchTouchEvent(ev)方法。他的代码地址
http://androidxref.com/7.0.0_r1/xref/frameworks/base/core/java/com/android/internal/policy/DecorView.java
看一下
由于DecorView是继承自FrameLayout的,所以下面进入了事件从ViewGroup向下分发的流程,下面的分发流程大家应该都清楚。
总结:
1.Activity是安卓四大组件之一,负责界面展示、用户交互与业务逻辑处理;2.Window就是负责界面展示以及交互的职能部门,就相当于Activity的下属,Activity的生命周期方法负责业务的处理;
3.View就是放在Window容器的元素,Window是View的载体,View是Window的具体展示。
相关文章推荐
- Android Activity、Window、View三者之间的关系
- Android中 dp,px,dpi三者之间的关系
- Android_View,ViewGroup,Window之间的关系
- Android 中Activity,Window和View之间的关系
- android中activity,window,view之间的关系
- ios-loadView,viewDidLoad,viewDidUnload三者之间的关系
- Android_View,ViewGroup,Window之间的关系
- Android快速理解Activity、View及Window&WindowManager之间关系
- android 图片和控件(ImageView)之间的关系 待解决??
- Android_View,ViewGroup,Window之间的关系 android activity,intent,service是什么关系?
- Android 中Activity,Window和View之间的关系
- Android自定义View专题四 View、Window、WindowManager和Activity之间的关系
- 【Android 界面效果10】Android中View,ViewGroup,Window之间的关系
- (转)Android 中Activity,Window和View之间的关系
- Android中 dp,px,dpi三者之间的关系
- android文件系统system-ramdisk-userdata三者之间的关系
- Android-Activity、Window、View之间的关系
- 【Android 界面效果10】Android中View,ViewGroup,Window之间的关系
- 移动开发:Android中 dp,px,dpi三者之间的关系
- Android 推流--分辨率、帧率和码率三者之间的关系