赞
踩
不管是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对应的ViewRootImpl
mParams
存储所有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:WindowManagerPolicy
WindowManagerPolicy
是窗口管理策略接口类,用来定义一个窗口策略遵循的规范,并提供WM所特定的UI行为,具体实现类为PhoneWIndowManager
,类在WMS
创建时被创建。
mSessions:ArraySet
元素类型为Session
,主要用于进程间通信,并且每一个应用程序都会对应一个Session
mWindowMap:WindowHashMap
key
值为IBinder
,value
值为WindowsState
,用来保存WMS各种窗口集合mFinishedStarting:arrayList
元素类型为AppWindowToken
,是WindowToken
子类,作用:
AppWindowToken
;activity
)的窗口(WindowState
)集合在一起,方便管理mFinishedStarting
就是用于存储已经完成启动的应用程序窗口的AppWindowToken
列表;
WindowToken
相关处理,比如有的窗口类型需要提供WindowToken
,没有提供就不会执行后面逻辑,有的窗口类型需要由WMS隐式创建WindowToken
WindowState
创建相关处理,将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
访问NotificationManagerService
NotificationManagerService
回调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
和Instrumentation
Application
对象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
方法,返回计算结果给onPostExecute
onProgressUpdate
在主线程中执行,当后台任务发生改变时,此方法调用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数量设置为默认的并行度。Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。