android主线程ActivityThread
ActivityThread在Android中它就代表了Android的主线程,但是并不是一个Thread类。
严格来说,UI主线程不是ActivityThread。ActivityThread类是Android APP进程的初始类,它的main函数是这个APP进程的入口。APP进程中UI事件的执行代码段都是由ActivityThread提供的。也就是说,Main Thread实例是存在的,只是创建它的代码我们不可见。ActivityThread的main函数就是在这个Main Thread里被执行的。
1.Java程序初始类中的main()方法,将作为该程序初始线程的起点,任何其他的线程都是由这个初始线程启动的。这个线程就是程序的主线程。
2.在Thread.java文件头部的说明中,有这样的介绍:Each application has at least one thread running when it is started, the main thread, in the main {@link ThreadGroup}.
源码如下:
http://androidxref.com/6.0.0_r1/xref/frameworks/base/core/java/android/app/ActivityThread.java
public final class ActivityThread { //... final H mH = new H(); final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>(); final ArrayMap<IBinder, Service> mServices = new ArrayMap<>();final ApplicationThread mAppThread = new ApplicationThread(); private class ApplicationThread extends ApplicationThreadNative { //... }private class H extends Handler {//... } //... }
1.ActivityThread.main()
public final class ActivityThread {//...private static ActivityThread sCurrentActivityThread;public static ActivityThread currentActivityThread() {return sCurrentActivityThread;}private void attach(boolean system) {sCurrentActivityThread = this;//... } public static void main(String[] args) {//....//创建Looper和MessageQueue对象,用于处理主线程的消息 Looper.prepareMainLooper();//创建ActivityThread对象ActivityThread thread = new ActivityThread(); //建立Binder通道 (创建新线程)thread.attach(false);Looper.loop(); //消息循环运行throw new RuntimeException("Main thread loop unexpectedly exited");}}
new ActivityThread()的局部变量通过attach()方法变成了全局变量sCurrentActivityThread,
通过currentActivityThread()方法可以得到当前线程
private void attach(boolean system) {sCurrentActivityThread = this;mSystemThread = system;if (!system) {//将mAppThread放到RuntimeInit类中的静态变量,也就是ApplicationThreadNative中的 this RuntimeInit.setApplicationObject(mAppThread.asBinder());final IActivityManager mgr = ActivityManagerNative.getDefault();try {mgr.attachApplication(mAppThread); //将mAppThread传入ActivityManagerService中} catch (RemoteException ex) {// Ignore }// Watch for getting close to heap limit.BinderInternal.addGcWatcher(new Runnable() {@Override public void run() {//... }});} else {// Don't set application object here -- if the system crashes,// we can't display an alert, we just want to die die die.android.ddm.DdmHandleAppName.setAppName("system_process",UserHandle.myUserId());try {mInstrumentation = new Instrumentation();ContextImpl context = ContextImpl.createAppContext(this, getSystemContext().mPackageInfo);mInitialApplication = context.mPackageInfo.makeApplication(true, null);mInitialApplication.onCreate();} catch (Exception e) {throw new RuntimeException("Unable to instantiate Application():" + e.toString(), e);}}//...}
1.调用 RuntimeInit.setApplicationObject() 方法,把对象mAppThread(Binder)放到了RuntimeInit类中的静态变量mApplicationObject中。
mAppThread的类型是ApplicationThread,它是ActivityThread的成员变量,定义和初始化如下:
final ApplicationThread mAppThread = new ApplicationThread();
2.ActivityThread与是怎么启动Activity呢?
ActivityThread的final H mH = new H()内部类H继承于Handler,通过handler消息机制,简单说Handler机制用于同一个进程的线程间通信。
Activity的生命周期都是依靠主线程的Looper.loop,当收到不同Message时则采用相应措施:
在H.handleMessage(msg)方法中,根据接收到不同的msg,执行相应的生命周期
例如:
当msg.what == LAUNCH_ACTIVITY就是调用handleLaunchActivity方法启动一个Activity,在handleLaunchActivity中又调用了performLaunchActivity方法来创建一个Activity实例,完成Activity的启动。 handleLaunchActivity源码如下:
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {//...调用performLaunchActivity方法完成Activity的启动Activity a = performLaunchActivity(r, customIntent);//... }
H继承与Handle,重写了handleMessage的方法
public final class ActivityThread { //... final H mH = new H();private class H extends Handler {//...声明的一些常量public void handleMessage(Message msg) {//...switch (msg.what) {//针对不同的常量,做不同的业务处理case LAUNCH_ACTIVITY: {//...启动一个ActivityhandleLaunchActivity(r, null, "LAUNCH_ACTIVITY");//...} break;case RELAUNCH_ACTIVITY: {//... handleRelaunchActivity(r);//...} break;case PAUSE_ACTIVITY: {//...handlePauseActivity((IBinder) args.arg1, false,(args.argi1 & USER_LEAVING) != 0, args.argi2,(args.argi1 & DONT_REPORT) != 0, args.argi3);maybeSnapshot();//...} break;//... }//... }private void maybeSnapshot() {//...这个方法主要统计snapshot }} }
这个类主要作用就是根据不同的情况处理各种业务,而且处理业务的方法一般是以handle开头,handleXXX的格式,如下:
handleActivityConfigurationChanged() handleBindApplication() handleBindService() handleCancelVisibleBehind() handleConfigurationChanged() handleCreateService() handleDestroyActivity() handleDispatchPackageBroadcast() handleLaunchActivity() handleLowMemory() handleMessage() handleNewIntent() handlePauseActivity() handleReceiver() handleRelaunchActivity() handleResumeActivity() handleSendResult() handleServiceArgs() handleStopActivity() handleStopService()
而这些函数有的又会调用到如下的performXXX系列函数完成最终的事件处理:
performDestroyActivity() performDestroyActivity() performLaunchActivity() performNewIntents() performPauseActivity() performPauseActivity() performRestartActivity() performResumeActivity() performStopActivity() performStopActivityInner() performUserLeavingActivity()
例如 从栈顶Activity的onPause到启动activityon的Resume过程
ActivityStack.startPausingLocked() IApplicationThread.schedulePauseActivity() ActivityThread.sendMessage() ActivityThread.H.sendMessage(); ActivityThread.H.handleMessage() ActivityThread.handlePauseActivity() ActivityThread.performPauseActivity() Activity.performPause() Activity.onPause() ActivityManagerNative.getDefault().activityPaused(token) ActivityManagerService.activityPaused() ActivityStack.activityPausedLocked() ActivityStack.completePauseLocked() ActivityStack.resumeTopActivitiesLocked() ActivityStack.resumeTopActivityLocked() ActivityStack.resumeTopActivityInnerLocked() ActivityStack.startSpecificActivityLocked
一般都是执行scheduleXXXActivity
然后ActivityThread sendMessage到handleMessage 然后handleXXXActivvity,最后处理performXXXActivity
3.主线程的消息又是哪来的呢?
当然是App进程中的其他线程通过Handler发送给主线程
ActivityThread框架是基于Binder通信的C/S结构,从图可知Server端是ActivityThread、ApplicationThread,Client是AMS(ActivityManagerService),而ApplicationThreadProxy可以看作AMS中Server代表
App进程则是我们常说的应用程序,主线程主要负责Activity/Service等组件的生命周期以及UI相关操作都运行在这个线程; 另外,每个App进程中至少会有两个binder线程 ApplicationThread和ActivityManagerProxy,除了图中画的线程,其中还有很多线程,比如signal catcher线程等,这里就不一一列举。
Binder用于不同进程之间通信,由一个进程的Binder客户端向另一个进程的服务端发送事务,比如图中线程2向线程4发送事务;而handler用于同一个进程中不同线程的通信,比如图中线程4向主线程发送消息。
例如:
需要暂停一个Activity
- 线程1的AMS中调用线程2的ApplicationThreadProxy;(由于同一个进程的线程间资源共享,可以相互直接调用,但需要注意多线程并发问题)
- 线程2通过binder传输到App进程的线程4;
- 线程4通过handler消息机制,将暂停Activity的消息发送给主线程;
- 主线程在looper.loop()中循环遍历消息,当收到暂停Activity的消息时,便将消息分发给ActivityThread.H.handleMessage()方法,再经过方法的调用,最后便会调用到Activity.onPause(),当onPause()处理完后,继续循环loop下去。
4.ApplicationThread
ActivityThread与启动Activity有关,那么ApplicationThread就与启动Application有关了
private class ApplicationThread extends ApplicationThreadNative {//... schedulePauseActivity()scheduleStopActivity()scheduleResumeActivity()scheduleSendResult()scheduleLaunchActivity()scheduleNewIntent()scheduleDestroyActivity()scheduleReceiver()scheduleCreateService()scheduleBindService()scheduleUnbindService()scheduleServiceArgs()scheduleStopService()bindApplication()scheduleConfigurationChanged()scheduleRegisteredReceiver()scheduleInstallProvider() }
可以看出来它继承了ApplicationThreadNative的,并且它内部有非常多的scheduleXXX的方法.以后看到thread调用这个方法 就可以往这边找。我们先说一下这些方法,这些方法由外部的ActivityThread的binder远程代理对象调用最终走到这里.这些 schedulexxx的方法会进一步的通过往外发送消息给mH这个消息队列.来做处理
IApplicationThread
http://androidxref.com/6.0.0_r1/xref/frameworks/base/core/java/android/app/IApplicationThread.java
可以看到ApplicationThreadNative和ApplicationThreadProxy都实现了这个接口
public interface IApplicationThread extends IInterface {void schedulePauseActivity() throws RemoteException;void scheduleStopActivity() throws RemoteException;void scheduleWindowVisibility(IBinder token, boolean showWindow) throws RemoteException;void scheduleSleeping() throws RemoteException;void scheduleResumeActivity() throws RemoteException;void scheduleSendResult(IBinder token, List<ResultInfo> results) throws RemoteException;void scheduleLaunchActivity() throws RemoteException;void scheduleRelaunchActivity() throws RemoteException;void scheduleNewIntent() throws RemoteException;void scheduleReceiver() throws RemoteException;void scheduleCreateBackupAgent() throws RemoteException;void scheduleDestroyBackupAgent()throws RemoteException;void scheduleCreateService() throws RemoteException;void scheduleBindService() throws RemoteException;void scheduleUnbindService() throws RemoteException;void scheduleServiceArgs() throws RemoteException;void scheduleStopService() throws RemoteException;void bindApplication() throws RemoteException;void scheduleExit() throws RemoteException;void scheduleSuicide() throws RemoteException;void scheduleConfigurationChanged() throws RemoteException;//... }
在来看看ApplicationThreadNative这个类
详细源码如下:
http://androidxref.com/6.0.0_r1/xref/frameworks/base/core/java/android/app/ApplicationThreadNative.java
public abstract class ApplicationThreadNative extends Binder implements IApplicationThread {//根据传入的不同参数决定返回不同的值.static public IApplicationThread asInterface(IBinder obj) {if (obj == null) {return null;}IApplicationThread in =(IApplicationThread)obj.queryLocalInterface(descriptor);if (in != null) {return in;}return new ApplicationThreadProxy(obj);}public ApplicationThreadNative() {attachInterface(this, descriptor);}@Overridepublic boolean onTransact(int code, Parcel data, Parcel reply, int flags)throws RemoteException {switch (code) {//... }}public IBinder asBinder(){return this;} }
说明:
该类实现业务接口IApplicationThread,非常标准的Binder模板.IApplicationThread extends IInterface它里面就是定义了非常多的通信的业务接口,也都是schedulexxx理解上对应到ApplicationThread那些方法。
该类首先是提供了一个静态的方法asInterface()用来获取IApplicationThread的Binder对象或者Binder代理对象,其它进程跨进程调用时候当传入的是BinderProxy那么就会返回一个ApplicationThreadProxy对象并把BinderProxy传入它的构造,而一般在本进程中调用的时候,就直接返回当前IApplicationThread对象,然后就是onTransact()函数了,里面通过不同的code对应到不同的case,进而调用不同的schedulexxx的方法,最终调用ApplicationThread中的schedulexxx方法。ApplicationThread这样就完成了作为服务端的构架,接下来就就是代理端的分析了.
前面我们知道跨进程调用asInterface的时候返回的是ApplicationThreadProxy对象,该类位于ApplicationThreadNative.java文件当中,是其内部类
ApplicationThreadProxy
public abstract class ApplicationThreadNative extends Binderimplements IApplicationThread {//...class ApplicationThreadProxy implements IApplicationThread {private final IBinder mRemote;public ApplicationThreadProxy(IBinder remote) {mRemote = remote;}public final IBinder asBinder() {return mRemote;}public final void schedulePauseActivity(IBinder token, boolean finished,boolean userLeaving, int configChanges, boolean dontReport) throws RemoteException {Parcel data = Parcel.obtain();data.writeInterfaceToken(IApplicationThread.descriptor);data.writeStrongBinder(token);data.writeInt(finished ? 1 : 0);data.writeInt(userLeaving ? 1 : 0);data.writeInt(configChanges);data.writeInt(dontReport ? 1 : 0);mRemote.transact(SCHEDULE_PAUSE_ACTIVITY_TRANSACTION, data, null,IBinder.FLAG_ONEWAY);data.recycle();}public final void scheduleStopActivity(IBinder token, boolean showWindow,int configChanges) throws RemoteException {//... }//...一些列的schedulexxx } }
说明,也是代理端的标准实现,实现了IApplicationThread 接口,然后实现接口中定义的业务方法,在每个方法中最终调用到了服务端的对应的schedulexxx方法中。当然这个过程是通过Binder通信调用的,例如上面通过mRemote变量和驱动去交互进而调用到server端, mRemote是一个BinderProxy对象.
关于IApplicationThread的Binder相关实现,有个需要注意的它没有趣ServiceManager中注册,走的是一个匿名的binder的方法,其实对于驱动来说都一样.暂时发现的是别的地方如AMS用的时候通过ActivityThread的接口获得到ApplicationThread的对象,然后传入到asInterface(),获取对应的IApplicationThread对象进行跨进程调用。
转载于:https://www.cnblogs.com/mingfeng002/p/10323668.html
android主线程ActivityThread相关推荐
- activitythread.java,android主线程ActivityThread
ActivityThread在Android中它就代表了Android的主线程,但是并不是一个Thread类. 严格来说,UI主线程不是ActivityThread.ActivityThread类是A ...
- android主线程报ANR的问题!
ANR (Application Not Responding) 默认情况下,在android中Activity的最长执行时间是5秒,BroadcastReceiver的最长执行时间则是10秒. 第一 ...
- Looper 需要手动 quit,那主线程 Looper 呢?
我们都清楚自行启动 Looper 的线程,在任务结束时需要手动调用 quit() 或 quitSafely() 终止 Looper 轮循.但对于其中细节似乎没有仔细思考过,抽上五分钟简要学习下! Lo ...
- Android ActivityThread(主线程或UI线程)简介
1. ActivityThread功能 它管理应用进程的主线程的执行(相当于普通Java程序的main入口函数),并根据AMS的要求(通过IApplicationThread接口,AMS为Client ...
- 腾讯Android面试:Handler中有Loop死循环,为什么没有阻塞主线程,原理是什么
面试官: Handler中有Loop死循环,为什么没有阻塞主线程,原理是什么 心理分析:该问题很难被考到,但是如果一旦问到,100%会回答不上来.开发者很难注意到一个主线程的四循环居然没有阻塞住主线程 ...
- Android切换到主线程
Android切换到主线程 方法一: view.post(Runnable action) textView.post(new Runnable() { @Override public void r ...
- android如何阻塞主线程,Android-Android如何避免阻塞主线程
Android的Handler和AsyncTask,可以避免阻塞主线程(UI线程),且UI的更新只能在主线程中完成,因此异步处理是不可避免的. AsyncTask,它使创建需要与用户界面交互的长时间运 ...
- android不能在主线程,android.os.NetworkOnMainThreadException 在4.0之后谷歌强制要求连接网络不能在主线程进行访问(示例代码)...
谷歌在4.0系统以后就禁止在主线程中进行网络访问了,原因是: 主线程是负责UI的响应,如果在主线程进行网络访问,超过5秒的话就会引发强制关闭, 所以这种耗时的操作不能放在主线程里.放在子线程里,而子线 ...
- android网络请求不能放在主线程
网络连接不能放在主线程 android 4.0 以上 网络连接不能放在主线程 4.0 以下 好像可以 在Android4.0以后,会发现,只要是写在主线程(就是Activity)中的HTTP请求 ...
最新文章
- 20+顶尖高校同时开打《王者荣耀》!实际上是一场科研battle,你能信?
- PathMatchingResourcePatternResolver通过适配符寻找符合条件的java类
- qt中用mysql获取所有的数据库、数据库中的表名
- 02-线性结构4 Pop Sequence
- Activity (项目实战:选择宝宝装备-UsersRegister)【Intent打开Activity、数据传递-回传、更新进度条】
- python运行出现数据错误_Python运行出错情况
- linux json 写sql注入,sql注入之AJAX(SQL Injection (AJAX/JSON/jQuery))
- 为什么老司机开车都不快?
- 文科辅修计算机科学,英属哥伦比亚大学专业详情.docx
- 基于触摸屏PLC的温度采集及简单控制
- Python状况:为什么PyPy是Python的未来?
- 关于win7快速启动栏以及显示桌面功能的还原
- android 画圆形图 获取圆形bitmap
- 为XYplorer添加右键菜单:“使用XYplorer打开”
- jq ajax简单使用方法
- 停车场寻车是怎么实现的?车库寻车有什么好办法?
- IntelliJ IDE
- Jmeter 之 Beanshell 用法
- Ubuntu下tar命令使用详解 .tar解压、.tar压缩
- BLAM源码解析(二)—— 从激光回调入手