Android : Activity,Window and View

看一下Activity是怎么通过View,Window等来用于自己的显示的。

Android : Activity,Window and View_第1张图片
上图是Activity的Lifecycle。
这里只想说一下按back键和按home键退出,重新打开一个activity的时候的流程。
第一次冷启动流程是:onCreate()->onStart()->onResume()
按Home键退出时:onPause()->onStop()
重新打开时:onStart()->onResume()
按Back键退出时:onPause()->onStop()->onDestroy()
重新打开时:onCreate()->onStart()->onResume()

1.entire lifetime : 这个生命周期发生在第一调用onCreate(Bundle)方法到最终的对onDestroy()的调用。一个Acitivity可以在onCreate()方法中对全局的状态进行初始化,在onDestroy中释放所有用到的资源。例如:如果需要一个后台运行的从网络中下载数据的线程,那么可以在onCreate()函数中进行创建,在onDestroy()中停止。

2.visible lifetime: 可视期介于调用 onStart 与 onStop 之间。此时Activity是可见的,但是不能响应用户事件。一个Activity在其生命周期中是有可能经历多个可视期的。在非常极端的情况下,系统也有可能终止一个处于可视期的活动,这种情况很少见。onStop 方法通常用于暂时或者停止那些用来更新UI的动画,线程,定时器,服务等,所以当活动不可见的时占用的系统资源是很少的。当活动由不可见状态转化为可见状态时,在 onStart 中再启动相关的线程和服务。onStart 和 onStop 同样也用来注册和取消注册(unregister)那些用来更新UI的广播接收者。在活动不可见时我们需要取消注册接受者(Receivers),特别是那些支持目的动作(Intent)以及更新UI的接收者。这也是为什么在onCreate()中setContentView()之后界面不是马上可以看到的原因!!!这个部分还需要看~~

3.foreground lifetime: 前台生命期从onResume()到onPause()。在这期间,这个activity在其他activity的前面,且正在与用户进行交互。一个activity可以很频繁的在Resumed与Paused状态之间进行切换。例如当设备Sleep时、一个Activity result被传递时、一个新的Intent被传递时等。所以为了有良好的用户体验,在 onResume 和 onPause 方法中的代码需要有更高的效率。foregroud的activity也可以在dumpsys meminfo里看到。

Activity的创建过程:parseBaseApk()->parseBaseApplication()->parseActivity()->

private Activity parseActivity(Package owner, Resources res,
            XmlPullParser parser, AttributeSet attrs, int flags, String[] outError,
            boolean receiver, boolean hardwareAccelerated)
            throws XmlPullParserException, IOException {
                 ...
                Activity a = new Activity(mParseActivityArgs, new ActivityInfo());
                ...
           }

onResume()的过程:

android.app.ActivityThread.performResumeActivity()
->android.app.Activity.performResume()
->android.app.Instrumentation.callActivityOnResume()
->com.sec.android.app.camera.Camera.onResume()

上面这些Activity的初始化以及回调函数的注册过程后面再看。

下面来看Activity和Window,View之间是什么关系,以及怎么利用View来画自己的界面的。
一个Activity可以画的部分,一般就是整个屏幕当中除了StatusBar以外的部分。
Android : Activity,Window and View_第2张图片

一个Activity,可以有很多个View。这个可以在自己的res/layout目录下看到

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" >
    <TextView  android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Hello World, MyActivity" />
    <ImageView  android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/imageView"/>

</LinearLayout>

像这样的一个Layout,会被组织成下面这样阶梯状的Layout和View。
Android : Activity,Window and View_第3张图片

这里的PRODUCT_POLICY是Android编译的时候指定的。有PhoneWindow和MIDWindow policy两种。一般都是用的PhoneWindow。
这个图里边可以看到一个Activity会有一个Window(或者说是PhoneWindow,Window类是个抽象类,PhoneWindow是Window类的唯一的实现类)。
总结几点就是:

1.Activity用自己Window,有人说肯定只有一个,也有人说可以有多个,有待确认。总之Activity会在onCreate()之前调用attach()。attach()函数会先创建Window(应该就是PhoneWindow了)。但不会创建DecorView。

2.Activity在onCreate()的时候setContentView()之后,会检查是否有DecorView。如果没有就会调用installDecor()函数创建一个DecorView和mContentParent,然后把setContentView()传入的View或者layoutID转成View,都加到mContentParent当中(mLayoutInflater.inflate(layoutResID, mContentParent)或者mContentParent.addView(view, params),看你是传layoutID还是View了)。之后调用onContentChanged()函数把view画上去。都只有一个PhoneWindow。PhoneWindow都有一个叫DecorView的子类。DecorView又继承自FrameLayout。FrameLayout又继承自ViewGroup。ViewGroup继承自View。所以说DecorView是Activity持有的最顶层的一个唯一的View(也可以说是上面图的ViewGroup吧~)。PhoneWindow中的DecorView是整个界面包含ActioBar(statusbar除外),那layout里边用户定义的view是PhoneWindow里边的mContentParent。之所以这样应该是ActionBar和背景都是只画一次的。(可以看installDecor()->generateLayout()函数)。
Android : Activity,Window and View_第4张图片

3.DecorView创建完需要加到WindowManager里的。这个过程可以看Activity里的setVisible()函数。这个函数内部调用了makeVisible()函数把DecorView加到WindowManager中。

void makeVisible() {  
       if (!mWindowAdded) {  
           ViewManager wm = getWindowManager();  
           wm.addView(mDecor, getWindow().getAttributes());  
           mWindowAdded = true;  
       }  
       mDecor.setVisibility(View.VISIBLE);  
   }  

4.界面上的点击等操作是由WindowManagerService接收消息,然后回调 Activity函数来处理。

怎么画上去的?

最后把界面画上去(应该是画到surface里边),是需要View来画的。每个View负责把自己负责的正方型内的内容画上去。当然要先测量自己的正方形大小,然后给视图进行布局,也就是确定视图的正确的位置。最后就是画了。分别由下面的三个函数完成。

onMeasure (int widthMeasureSpec, int heightMeasureSpec) { }

onLayout (boolean changed,int left, int top,int rig , ht, int bottom) { }

onDraw (Canvas canvas) { }

下面的链接有比较好的说明,先不再赘述。
http://blog.csdn.net/guolin_blog/article/details/16330267

问题是把要画的View都加到DecorView里边了,DecorView也加到WindowManger了,到什么时间点才会一层一层调用每个View的回到函数来画呢?这个流程可以看下面两张图。
Android : Activity,Window and View_第5张图片
Android : Activity,Window and View_第6张图片
http://www.07net01.com/2015/07/866214.html

一层一层调用draw()的过程如下图:
Android : Activity,Window and View_第7张图片
这个与上面说的画的相符,就是ViewRoot开始,一层一层调用每个View的onDraw()函数把view的内容画上去(Canvas也是ViewRoot创建传下去的)。但onDraw()画上去之后不会马上从屏幕上看到,这个和Surfac,SurfaceFlinger相关。

1.一个Activity可以有多个Window ??
2.一个Window可以有多个Surface ???

SurfaceView比较特殊!!!

SurfaceView是拥有自己画图空间的唯一的View。SurfaceView的存在是为了克服View画图的时间点是由ViewRoot决定的短板。SurfaceView在调用onDraw()的时候,会在自己需要画的位置保留一块透明的所谓punch hole。真正画这块内容是SurfaceView会利用SurfaceHolder和其他辅助线程。

ActivityManager VS OOM

Android : Activity,Window and View_第8张图片

待续..

你可能感兴趣的:(Android : Activity,Window and View)