最近在准备实习,一直在搜寻一些Android方面基础的知识,现在做一个小小的总结。
-
1.ViewRootImpl会调用performTraversals(),其内部会调用performMeasure()、performLayout、performDraw()。
-
2.performMeasure()会调用最外层的ViewGroup的measure()-->onMeasure(),ViewGroup的onMeasure()是抽象方法,但其提供了measureChildren(),这之中会遍历子View然后循环调用measureChild()这之中会用getChildMeasureSpec()+父View的MeasureSpec+子View的LayoutParam一起获取本View的MeasureSpec,然后调用子View的measure()到View的onMeasure()-->setMeasureDimension(getDefaultSize(),getDefaultSize()),getDefaultSize()默认返回measureSpec的测量数值,所以继承View进行自定义的wrap_content需要重写。
-
3.performLayout()会调用最外层的ViewGroup的layout(l,t,r,b),本View在其中使用setFrame()设置本View的四个顶点位置。在onLayout(抽象方法)中确定子View的位置,如LinearLayout会遍历子View,循环调用setChildFrame()-->子View.layout()。
-
4.performDraw()会调用最外层ViewGroup的draw():其中会先后调用background.draw()(绘制背景)、onDraw()(绘制自己)、dispatchDraw()(绘制子View)、onDrawScrollBars()(绘制装饰)。
-
5.MeasureSpec由2位SpecMode(UNSPECIFIED、EXACTLY(对应精确值和match_parent)、AT_MOST(对应warp_content))和30位SpecSize组成一个int,DecorView的MeasureSpec由窗口大小和其LayoutParams决定,其他View由父View的MeasureSpec和本View的LayoutParams决定。ViewGroup中有getChildMeasureSpec()来获取子View的MeasureSpec。
-
6.三种方式获取measure()后的宽高:
-
1.Activity#onWindowFocusChange()中调用获取
-
2.view.post(Runnable)将获取的代码投递到消息队列的尾部。
-
3.ViewTreeObservable.
-
二.、activty的加载过程
-
1.Activity中最终到startActivityForResult()(mMainThread.getApplicationThread()传入了一个ApplicationThread检查APT)
->Instrumentation#execStartActivity()和checkStartActivityResult()(这是在启动了Activity之后判断Activity是否启动成功,例如没有在AM中注册那么就会报错)
->ActivityManagerNative.getDefault().startActivity()(类似AIDL,实现了IAM,实际是由远端的AMS实现startActivity())
->ActivityStackSupervisor#startActivityMayWait()
->ActivityStack#resumeTopActivityInnerLocked
->ActivityStackSupervisor#realStartActivityLocked()(在这里调用APT的scheduleLaunchActivity,也是AIDL,不过是在远端调起了本进程Application线程)
->ApplicationThread#scheduleLaunchActivity()(这是本进程的一个线程,用于作为Service端来接受AMS client端的调起)
->ActivityThread#handleLaunchActivity()(接收内部类H的消息,ApplicationThread线程发送LAUNCH_ACTIVITY消息给H)
->最终在ActivityThread#performLaunchActivity()中实现Activity的启动完成了以下几件事: -
2.从传入的ActivityClientRecord中获取待启动的Activity的组件信息
-
3.创建类加载器,使用Instrumentation#newActivity()加载Activity对象
-
4.调用LoadedApk.makeApplication方法尝试创建Application,由于单例所以不会重复创建。
-
5.创建Context的实现类ContextImpl对象,并通过Activity#attach()完成数据初始化和Context建立联系,因为Activity是Context的桥接类,
最后就是创建和关联window,让Window接收的事件传给Activity,在Window的创建过程中会调用ViewRootImpl的performTraversals()初始化View。 -
6.Instrumentation#callActivityOnCreate()->Activity#performCreate()->Activity#onCreate().onCreate()中会通过Activity#setContentView()调用PhoneWindow的setContentView()
更新界面。
三、Activity的启动模式
-
1.standard:默认标准模式,每启动一个都会创建一个实例,
-
2.singleTop:栈顶复用,如果在栈顶就调用onNewIntent复用,从onResume()开始
-
3.singleTask:栈内复用,本栈内只要用该类型Activity就会调到栈顶复用,从onResume()开始
-
4.singleInstance:单例模式,除了3中特性,系统会单独给该Activity创建一个栈
1.standard:默认标准模式,每启动一个都会创建一个实例,
2.singleTop:栈顶复用,如果在栈顶就调用onNewIntent复用,从onResume()开始
3.singleTask:栈内复用,本栈内只要用该类型Activity就会调到栈顶复用,从onResume()开始
4.singleInstance:单例模式,除了3中特性,系统会单独给该Activity创建一个栈
四、Activity缓存方法
-
1.配置改变导致Activity被杀死,横屏变竖屏:在onStop之前会调用onSaveInstanceState()保存数据在重建Activity之后,会在onStart()之后调用onRestoreInstanceState(),并把保存下来的Bundle传给onCreate()和它会默认重建Activity当前的视图,我们可以在onCreate()中,回复自己的数据。
-
2.内存不足杀掉Activity,优先级分别是:前台可见,可见非前台,后台
五、Service的生命周期(两种启动方法,有什么不同)
-
1.context.startService() ->onCreate()- >onStart()->Service running-->(如果调用context.stopService() )->onDestroy() ->Service shut down
-
1.如果Service还没有运行,则调用onCreate()然后调用onStart();
-
2.如果Service已经运行,则只调用onStart(),所以一个Service的onStart方法可能会重复调用多次。
-
3.调用stopService的时候直接onDestroy,
-
4.如果是调用者自己直接退出而没有调用stopService的话,Service会一直在后台运行。该Service的调用者再启动起来后可以通过stopService关闭Service。
-
-
2.context.bindService()->onCreate()->onBind()->Service running-->onUnbind() -> onDestroy() ->Service stop
-
1.onBind将返回给客户端一个IBind接口实例,IBind允许客户端回调服务的方法,比如得到Service运行的状态或其他操作。
-
2.这个时候会把调用者和Service绑定在一起,Context退出了,Service就会调用onUnbind->onDestroy相应退出。
-
3.所以调用bindService的生命周期为:onCreate --> onBind(只一次,不可多次绑定) --> onUnbind --> onDestory。
-