不管是Activity,Dialog还是Toast,它们视图都是附加在window上的,window才是view的直接管理者。
FLAG_NOT_FOCUSABLE:表示不需要获取焦点,也不需要接收各种输入事件,同时启用FLAG_NOT_TOUCH_MODE 最终事件直接会传递给下层具有焦点的windowFLAG_NOT_TOUCH_MODE ,系统会将当前window区域以外的单击事件传递给底层的window,当前区域内的单击事件自己处理,一般需要开启此标记,否则window将无法收到单击事件。FLAG_SHOW_WHEN_LOCKED:开启此模式,让window显示在锁屏界面上。viewRootImpl并将View添加到列表中mViews存储所有window对应的viewmRoots存储所有window对应的ViewRootImplmParams存储所有window对应的布局参数mDyingViews存储正在删除的view对象ViewRootImpl来更新并完成添加过程通过findViewLocked来查找待删除的View索引,查找过程建立数组索引遍历,在调用removeViewLocked进一步删除。
删除提供两个接口,removeView与removeViewImmediate,异步与同步删除,同步删除window会发生错误,而异步删除由viewRootImpl的die方法完成,die发送一个请求删除消息后就返回,将view添加到DyingViews中。
调用updateViewLayout让新的LayoutParams替换老的LayoutParams,再更新viewRootImpl中的LayoutParams,并在viewRootImpl中的scheduleTraversals对view进行重新布局,还会通过windowSession来更新window视图,这个过程由relayoutWindow具体实现,它是IPC进程。
WMS创建涉及三个线程,分别是system_server、android:display、android:ui之间关系
system_server线程中执行了systemServer的startOtherServices方法,在该方法中调用WMS的main方法,main方法会创建WMS,创建过程在android:display线程中实现,创建WMS优先级更高,因此system_sever线程要等WMS创建完成后,处于等待状态的system_server线程才会被唤醒从而继续执行**initPolicy方法,在该方法中又会调用PowerManagerService的init方法,PWM的init方法会在android:ui线程中运行,它的优先级要高于android:display线程,因此android:display要等待init方法执行完毕后,android:display才会被唤醒继续执行init方法执行完毕后,android:display线程就完成了WMS创建,等待的system_server线程被唤醒继续执行WMS的main方法后的逻辑,比如WMS的displayReady方法用来初始化屏幕显示信息。mPolicy:WindowManagerPolicyWindowManagerPolicy是窗口管理策略接口类,用来定义一个窗口策略遵循的规范,并提供WM所特定的UI行为,具体实现类为PhoneWIndowManager,类在WMS创建时被创建。
mSessions:ArraySet元素类型为Session,主要用于进程间通信,并且每一个应用程序都会对应一个Session
mWindowMap:WindowHashMapkey值为IBinder,value值为WindowsState,用来保存WMS各种窗口集合mFinishedStarting:arrayList元素类型为AppWindowToken,是WindowToken子类,作用:
AppWindowToken;activity)的窗口(WindowState)集合在一起,方便管理mFinishedStarting就是用于存储已经完成启动的应用程序窗口的AppWindowToken列表;
WindowToken相关处理,比如有的窗口类型需要提供WindowToken,没有提供就不会执行后面逻辑,有的窗口类型需要由WMS隐式创建WindowTokenWindowState创建相关处理,将WindowToken与WindowState相关联DisplayContent,完成窗口添加到系统前的准备工作ViewRootImpl列表,布局参数列表与View列表删除与Window对应的原色WindowManagerService是WindowManager的管理者的
它是窗口管理者,负责窗口启动、添加、删除,另外窗口大小与层级也是由它进行管理。管理的核心成员有:DisplayContent、WindowToken与WindowState
窗口间进行切换时,使用动画更加炫酷些,是由WMS的动画子系统负责,管理者为WindowAnimator
通过窗口触摸而产生的触摸事件,InputManagerService会对触摸事件进行管理,寻找最合适的窗口来处理触摸反馈事件
Surface管理窗口并不具有绘制功能,每个窗口都需要一块Surface来供自己绘制,为每个窗口分配Surface由WMS完成的
由activity的setContentView看出,它的具体实现交给了PhoneWindow
DecorView就创建DecorView的mContentParent中activity的onContentChanged方法通知activity的视图发生改变diaolog视图添加到DecorView中DecorView添加到window中必须采用activity的context,否则采用application的context会报错.是由于没有应用token导致,而token只有activity有,可以指定为系统类型window就可以正常弹出。
dialog.getWindow().setType(LayoutParams.TYPE_SYSTEM_ERROR)android.permission.SYSTEM_ALTER_WINDOW它有定时功能,采用handler,内部有两类IPC
Toast访问NotificationManagerServiceNotificationManagerService回调Toast的TN接口Toast的延时时长只有2s与3.5s
**Android 7.0与8.0区别是,与AMS进行进程间通信采用的AIDL技术去掉了此前一直沿用的activityManagerProxy与applicationThreadProxy等代理类。
activityManagerNative,getDefault()的startActivity方法完成,AMS是一个Binder,这个binder对象采用单例模式对外提供,Singletn是一个单例封装类,第一次调用它的get通过create来初始化AMS的binder对象。ActivityManager.getDefault()实际上是ActivityManagerService(AMS)
ActivityStackSupervisor和ActivityStack之间传递顺序
startActivityMayWait -> startActivityLocked -> startActivityUncheckedLocked ->resumeTopActivitiesLocked -> resumeTopActivityInnerLocked ->startSpecificActivityLocked -> realStartActivityLocked
其中resumeTopActivitiesLocked与resumeTopActivityInnerLocked在ActivityStack中,其余在ActivityStackSupervisor。ActivityThread的handleLaunchActivity方法实现。最后performLaunchActivity完成activity对象创建与启动过程。
performLaunchActivity完成事:
ActivityClientRecorf中获取待启动activity的组件信息Instrumentation的newactivity方法使用类加载器创建activity对象LoadedApk的makeApplication来创建Application对象,其中Application不会重复创建ContextImpl对象通过activity的attach来完成一些重要数据初始化,ContextImpl是context的具体实现,在attach方法中,activity还会完成window创建并建立关联windowonCreate方法Service启动过程从ContextWrapper的startService开始,从ContextWrapper实现看出,大部分操作通过mBase实现,是一个桥接模式。然后调用ContextImpl的startService实现,又调用了ActivityManager.getDefault()实际上是ActivityManagerService(AMS)的startServic方法,Services对象类型ActiviteServices是一个辅助AMS进行Service管理,包括启动,绑定,停止。ActiviteServices的startServiceLocked尾部的startServiceInnerLocked,ServiceRecord描述一个Service记录,贯穿整个启动过程,又交给了bringUpServiceLocked,然后交给realStartServiceLocked处理,方法里又调用了ApplicationThread的scheduleCreateService通过发消息交给ActivityThread的handleCreateService处理handleCreateService做的事:
Application,调用onCreateContextImpl与service的attach建立二者之间关系service的oncreate将servic对象存储在activityThread列表中从ContextWrapper开始,然后调用ContextImpl的bindService,调用bindServiceCommon方法做了两件事:
ServiceConnection对象转化为ServiceDispatcher.InnerConnection对象,因为服务绑定可能跨进程bindServiceCommon通过AMS完成Service的具体绑定,调用AMS的bindService方法绑定过程调用ActivityThread的scheduleBindService,实现在ActiviteServices的requestServiceBindingLocked方法中。然后ApplicationThread的scheduleBindService发消息进行绑定,调用handleBindService,根据service的token取出service对象,然后调用onBinder方法,就绑定了,但客户端不知道是否成功连接service还需要调用AMS的publishService方法,多次绑定相同的service,onBinder方法只会执行一次。
PackManagerService来完成整个注册过程ContextWrapper的registerReceiver方法开始,然后调用ContextImpl的registerReceiverInternal方法, 首先从mPackageInfo中获取IIntentReceiver对象,然后采用跨进程方式向AMS发送广播注册,之所以采用IIntentReceiver,由于BroadcastReceiver作为android不能直接跨进程。getReceiverDispatcher方法重新创建一个ReceiverDispatcher对象并将其板寸的InnerReceiver对象作为返回值返回,其中InnerReceiver和BroadcastReceiver在ReceiverDispatcher的构造方法中保存广播真正实现在AMS中,最终把远程的InnerReceiver对象以及IntentFilter对象存储起来。
广播发送仍然是从ContextWrapper的sendBroadcast开始,交给ContextImpl的sendBroadcast,然后在AMS的broadcastIntent方法中开始,调用broadcastIntentLocked方法。
intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES)表示在android 5.0中,默认情况下广播不会发送给已经停止的应用,而FLAG_INCLUDE_STOPPED_PACKAGES表示包含已经停止的应用,广播会发送给停止的应用。当这两种状态共存,以FLAG_INCLUDE_STOPPED_PACKAGES为准。
一个应用处于停止有两种情形:
在broadcastIntentLocked内部,根据intent-filter查找匹配广播接收者并经过一系列过滤,将满足条件的添加到BroadcastQueue中。然后在BroadcastQueue中调用scheduleBroadcastsLocked方法,通过handler发消息让processNextBroadcast处理。
调用LoadedApk类的performReceive方法,创建Args对象,它实现了Runnable接口,run方法中:
final BroadcastReceiver receiver = mReceiver; receiver.setPendingResult(this);
receiver.onReceive(mContext, intent);这个时候BroadcastReceiver的onReceive方法执行,应用已经接收广播了。
contentProvider所在的进程启动时,contentProvider会同时启动并发布AMS中,**注意:这个时候ContentProvider的onCreate要先于Application的onCreate方法执行。activityThread的main方法,main方法是一个静态方法,在main方法中创建activityThread实例并创建主线程的消息队列,然后在activityThread的attach方法中会远程调用AMS的attachApplication方法并将ApplicationThread对象提供给AMS。ApplicationThread是一个Binder对象,主要用于ActivityThread与AMS之间通信。在AMS的attachApplication方法中,会调用applicationThread的bindApplication方法,同样跨进程完成,bindApplication逻辑经过applicationThread中mH handler切换到activitThread中执行,具体方法是handleBinderApplication,方法中activityThread会优先加载contentProvider然后在调用application的oncreate方法。
ContentProvider一般都是单实例,是由android:multiprocess决定,为false是单实例,为true多实例。ActivityThread的handleBinderApplication,则完成Application创建以及ContentProvider创建:ContentImpl和InstrumentationApplication对象ContentProvider并调用onCreate方法Application的onCreate方法handler运行底层需要MessageQueue与Looper支撑
MessageQueue使用来存储消息的,以队列形式插入与删除消息,内部存储结构并不是真正的队列,而是用单链表数据结构来实现的消息存储。Looper用来处理消息,以无限循坏的方法是查看是否有新的消息,有的话就进行处理,否则一直处于等待。还有一个特殊的概念ThreadLocal,作用可以在每个线程中存储数据。在handler内部可以通过ThreadLocal来获取每个线程的Looper,它可以在不同线程互不干扰存储并提供数据。
如果线程没有默认的Looper,那么使用handler就必须创建Looper。ActivityThread被创建时会初始化Looper,这就是默认可以在主线程中使用handler。handler的post方法将一个runnable投递到handler内部的Looper中去处理,也可以通过send发消息。当handler的send方法被调用,它会调用MessageQueue的equeueMessage方法将消息存储到队列中,然后Looper就会处理这个消息,然后handlerMessage方法就会调用。Looper运行在创建handelr所在的线程中,这样handler的处理逻辑就会在创建handler线程中执行。ThreadLocal,比如要获取当前线程的Looper,但不同线程有不同Looper。采用ThreadLocal可以让监听器作为线程内的全局对象存在,线程内部只需通过get方法获取监听器。
主要包含插入与读取,分别对应equeueMessage与next方法
从源码中看出equeueMessage的实现主要是单链表的插入操作。
next方法是一个无限循坏方法,如果这个消息队列没有消息,next就会一直阻塞在这里,当有消息,就会返回这条消息,并将从单链表移除。
查看是否有消息,有就处理,没有就一直阻塞。
通过Looper.prepare()创建Looper,Looper.loop()开启消息循坏
可以在主线程中创建Looper调用prepareMainLooper,调用getMainLooper在主线程获取Looper。
调用quit与quitSafely来退出Looper。区别:
quit直接退出LooperquitSafely设定退出标记,只有消息处理完毕才会安全退出。手动创建Looper,那么在所有事情处理完毕后调用quit来退出Looper来终止消息循坏,否则一直处于等待状态。loop方法是一个死循环,只有MessageQueue的next方法返回为空时,才会跳出循坏,所以不使用时必须通过quit或者quitSafely退出循环,否则会造成内存泄漏等其他问题
消息发送与接收,可以通过post与send来实现,post方法最终通过send方法实现。handler发送消息仅仅向消息队列中插入一条消息。
handler处理消息过程
message的callback是否为空,不为空,就通过handleCallback处理mCallback是否为空,不为空就调用mCallback.handleMessage处理handlerMessage处理handler还有一个特殊的构造方法,通过特定的Looper构造Handler,如果当前线程没有Looper,就会抛异常。
主线程消息循坏
ActivityThread,入口为main方法,prepareMainLooper创建主线程Looper与messageQueue.ActivityThread通过ApplicationThread和AMS进行进程间通信,AMS以进程间通信方式完成ActivityThread请求回调ApplicationThread的binder方法,然后ApplicationThread向H发送消息,H收到消息将ApplicationThread逻辑切换到主线程执行。**volatile :保证可见性,有序性,但不能保证原子性
使用volatile必须具备以下两个条件:
第一个条件就是:自增,自减
第二个条件就是:包含一个不变式:下界总是小于或等于上界
voliate可以用于很多场景:
ArrayBlockingQueue:由数组结构组成的有界阻塞队列;
按照先进先出原则对元素排列,默认情况下不保证公平访问队列,公平访问队列指的是:阻塞所有的生产者与消费者,当队列可用时,按照阻塞的先后顺序进行访问,先阻塞生产者,往里面插入元素;阻塞消费者,从队列里面获取元素;LinkedBlockingQueue:由链表构成的有界阻塞队列,先进先出原则对元素进行排序;只有当队列的缓存区达到缓存容量最大值,才会阻塞队列,直至消费者从队列消费一份数据,生产者线程才会被唤起;PriorityBlockingQueue:支持优先级排序的无界阻塞队列;默认元素升序排序;可以自定义compareTo()方法进行排序;DelayQueue:延时获取元素的无界阻塞队列;创建元素可以指定元素的时间,只有到元素到期时,才会取走元素;SynchronousQueue:不储存元素的阻塞队列;每插入操作必须等待另一个线程的移除操作;因此队列中没有任何元素;LinkedTransferQueue:由链表构成的无界阻塞队列;LinkedBlockingDeque:由链表组成的双向阻塞队列;可从队列的两端插入和移除元素;AsyncTask是一个轻量级异步任务类,在线程池中执行后台任务,将最终结果传递给主线程中,并在主线程中更新UI,它封装了Thread与handler
AsyncTask线程池配置的参数:
4.任务队列容量128
内部方法:
onPreExecute在主线程中执行,异步任务开始前调用,用于做准备工作doInBackground在线程池中执行,调用publishProgress更新任务,publishProgress调用onProgressUpdate方法,返回计算结果给onPostExecuteonProgressUpdate在主线程中执行,当后台任务发生改变时,此方法调用onPostExecute在主线程执行,result参数是后台任务返回值AsyncTask一些条件限制:
AsyncTask必须在主线程中加载,第一次访问AsyncTask必须发生在主线程,在android4.1及以上已经被系统自动完成,在android5.0源码中,查看activityThread的main方法,它会调用asyncTask的init方法,这就是它必须在主线程中加载的条件。
从源码可知sHandler是一个静态Handler对象,能够将执行环境切换到主线程中,这就要求sHandler在主线程中创建,静态成员会在加载类时进行初始化,变相要求AsyncTask必须在主线程中加载。AsyncTask对象必须在主线程中创建execute必须在UI线程调用onPreExecute,doInBackground,onProgressUpdate方法AsyncTask对象只能执行一次,只能调用一次execute方法,否则会报异常executeOnExecute方法并行执行任务AsyncTask有两个线程池(SerialExecutor与THREAD_POOL_EXECUTOR)和一个IntentHandler,SerialExecutor用于任务排队,THREAD_POOL_EXECUTOR用于真正执行任务,IntentHandler用于将执行环境从线程池中切换到主线程。
它继承自Thread,在run方法中通过Looper.prepare创建消息队列,通过Looper.loop开启消息循坏。普通Thread的run方法执行一个耗时任务,而它内部创建消息队列,外界需要通过handler的消息方式来通知它执行一个具体的任务。**
使用场景Intentservice,不需要使用handlerThread时,使用quit,quitsafely终止执行。
IntentService执行后台耗时任务,当任务执行后它会停止。适合高优先级的后台任务。
当onHandlerThread方法执行结束后,IntentService采用stopSelf(int startId)来尝试停止服务,而使用stopSelf()方法则会立刻停止所有服务,而stopSelf(int startId)等待所有消息都处理完毕后才会终止,尝试停止服务之前判断最近启动的服务次数是否与startId相等,相等则停止。
Executor为一个接口,真正实现是ThreadPoolExecutor
ThreadPoolExecutor内部参数:
coorPoolSize 核心线程数maximumPoolSize 最大线程数,达到这个数值,后台任务会阻塞keepAliveTime 非核心线程闲置时的超时时长unit 时间单位workQueue 任务队列,线程池的execute提交的Runnable对象会存储在这个参数中threadFactory 线程工厂RejectedExecutionHandler:饱和策略,这是当任务队列与线程池都满的情况下,所采取的应对策略,默认是AbordPolicy,表示无法处理新任务,抛出RejectedExecutionExecption异常,还有三种策略:
CallerRunsPolicy:用调用者所在的线程来处理任务,提供简单的反馈机制,能够减缓新任务的提交速度DiscardPolicy:不能执行的任务,并将任务删除DiscardOldestPolicy:丢弃列表最近的任务,并执行该任务FIxedThreadPool线程数量固定的线程池,当线程处于空闲状态,它们并不会回收,只有核心线程,能够快速响应外界请求,任务队列没有大小限制
CacheThreadPool只有非核心线程,线程数无限大,空闲线程超时时长为60s,任务队列为SynchronousQueue,是一个无法存储元素的队列。适合执行大量耗时较少的任务。
ScheduleThreadPool核心线程数量固定,非核心线程数没有限制,用于执行定时任务与具有固定周期的重复任务。采用DelayWorkQueue是无界的。
SingleThreadExecutor只有一个核心线程,没有非核心线程,任务都在同一个线程中顺序执行,无需考虑同步问题。
Excecutors.newWorkStealingPool:JDK8引入,创建持有足够线程的线程池支持给定的并行度,并通过使用多个队列减少竞争,把CPU数量设置为默认的并行度。