文档章节

Android之ActivityThread

思想永无止境
 思想永无止境
发布于 2016/11/04 11:59
字数 1362
阅读 7
收藏 0

1. ActivityThread功能

    它管理应用进程的主线程的执行(相当于普通Java程序的main入口函数),并根据AMS的要求(通过IApplicationThread接口,AMS为Client、ActivityThread.ApplicationThread为Server)负责调度和执行activities、broadcasts和其它操作。

    在Android系统中,在默认情况下,一个应用程序内的各个组件(如Activity、BroadcastReceiver、Service)都会在同一个进程(Process)里执行,且由此进程的【主线程】负责执行。

    在Android系统中,如果有特别指定(通过android:process),也可以让特定组件在不同的进程中运行。无论组件在哪一个进程中运行,默认情况下,他们都由此进程的【主线程】负责执行。

    【主线程】既要处理Activity组件的UI事件,又要处理Service后台服务工作,通常会忙不过来。为了解决此问题,主线程可以创建多个子线程来处理后台服务工作,而本身专心处理UI画面的事件。

     【主线程】的主要责任:

       • 快速处理UI事件。而且只有它才处理UI事件, 其它线程还不能存取UI画面上的对象(如TextView等),此时, 主线程就叫做UI线程。基本上,Android希望UI线程能根据用户的要求做出快速响应,如果UI线程花太多时间处理后台的工作,当UI事件发生时,让用户等待时间超过5秒而未处理,Android系统就会给用户显示ANR提示信息。

         只有UI线程才能执行View派生类的onDraw()函数。

      • 快速处理Broadcast消息。【主线程】除了处理UI事件之外,还要处理Broadcast消息。所以在BroadcastReceiver的onReceive()函数中,不宜占用太长的时间,否则导致【主线程】无法处理其它的Broadcast消息或UI事件。如果占用时间超过10秒, Android系统就会给用户显示ANR提示信息。

      注意事项:

      • 尽量避免让【主线程】执行耗时的操作,让它能快速处理UI事件和Broadcast消息。

      • BroadcastReceiver的子类都是无状态的,即每次启动时,才会创建其对象,然后调用它的onReceive()函数,当执行完onReceive()函数时,就立即删除此对象。由于每次调用其函数时,会重新创建一个新的对象,所以对象里的属性值,是无法让各函数所共享。   

1.1 Thread与SurfaceView

      View组件由UI线程(主线程)所执行。如果需要迅速更新UI画面或UI画图需要较长时间,则需要使用SurfaceView。它可由后台线程(background thread)来执行,而View只能由UI(主)线程执行。SurfaceView内有高效的rendering机制,可以让后台线程快速刷新Surface的内容。

      View ---> UI(主)线程

      SurfaceView ---> 后台线程   


2. Android应用程序主线程stack

    在一个只有Activity派生类的应用程序中,它包含如下线程:


    main线程stack如下:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. at android.os.MessageQueue.nativePollOnce(Native Method)      
  2. at android.os.MessageQueue.next(MessageQueue.java:118)    
  3. at android.os.Looper.loop(Looper.java:118)    
  4.   
  5. at android.app.ActivityThread.main(ActivityThread.java:4424)    // Java main入口函数  
  6.   
  7. at java.lang.reflect.Method.invokeNative(Native Method)   
  8. at java.lang.reflect.Method.invoke(Method.java:511)   
  9. at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)    
  10. at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)   
  11. at dalvik.system.NativeStart.main(Native Method)      

     JDWP线程stack如下:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. at org.apache.harmony.dalvik.ddmc.DdmVmInternal.getStackTraceById(Native Method)      
  2. at android.ddm.DdmHandleThread.handleSTKL(DdmHandleThread.java:131)   
  3. at android.ddm.DdmHandleThread.handleChunk(DdmHandleThread.java:77)   
  4. at org.apache.harmony.dalvik.ddmc.DdmServer.dispatch(DdmServer.java:171)      
  5. at dalvik.system.NativeStart.run(Native Method)   

3. IApplicationThread关系图



4. ActivityThread类

   ActivityThread类即代表Application主线程。

4.1 类中关键信息

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * This manages the execution of the main thread in an 
  3.  * application process, scheduling and executing activities, 
  4.  * broadcasts, and other operations on it as the activity 
  5.  * manager requests. 
  6.  * 
  7.  * {@hide} 
  8.  */  
  9. public final class ActivityThread {  
  10.   
  11.     static ContextImpl mSystemContext = null;  
  12.   
  13.     static IPackageManager sPackageManager;  
  14.       
  15.     // 创建ApplicationThread实例,以接收AMS指令并执行  
  16.     final ApplicationThread mAppThread = new ApplicationThread();  
  17.   
  18.     final Looper mLooper = Looper.myLooper();  
  19.   
  20.     final H mH = new H();  
  21.   
  22.     final HashMap<IBinder, ActivityClientRecord> mActivities  
  23.             = new HashMap<IBinder, ActivityClientRecord>();  
  24.       
  25.     // List of new activities (via ActivityRecord.nextIdle) that should  
  26.     // be reported when next we idle.  
  27.     ActivityClientRecord mNewActivities = null;  
  28.       
  29.     // Number of activities that are currently visible on-screen.  
  30.     int mNumVisibleActivities = 0;  
  31.       
  32.     final HashMap<IBinder, Service> mServices  
  33.             = new HashMap<IBinder, Service>();  
  34.       
  35.     Application mInitialApplication;  
  36.   
  37.     final ArrayList<Application> mAllApplications  
  38.             = new ArrayList<Application>();  
  39.   
  40.     static final ThreadLocal<ActivityThread> sThreadLocal = new ThreadLocal<ActivityThread>();  
  41.     Instrumentation mInstrumentation;  
  42.   
  43.     static Handler sMainThreadHandler;  // set once in main()  
  44.   
  45.     static final class ActivityClientRecord {  
  46.         IBinder token;  
  47.         int ident;  
  48.         Intent intent;  
  49.         Bundle state;  
  50.         Activity activity;  
  51.         Window window;  
  52.         Activity parent;  
  53.         String embeddedID;  
  54.         Activity.NonConfigurationInstances lastNonConfigurationInstances;  
  55.         boolean paused;  
  56.         boolean stopped;  
  57.         boolean hideForNow;  
  58.         Configuration newConfig;  
  59.         Configuration createdConfig;  
  60.         ActivityClientRecord nextIdle;  
  61.   
  62.         String profileFile;  
  63.         ParcelFileDescriptor profileFd;  
  64.         boolean autoStopProfiler;  
  65.   
  66.         ActivityInfo activityInfo;  
  67.         CompatibilityInfo compatInfo;  
  68.         LoadedApk packageInfo; //包信息,通过调用ActivityThread.getPapckageInfo而获得  
  69.   
  70.         List<ResultInfo> pendingResults;  
  71.         List<Intent> pendingIntents;  
  72.   
  73.         boolean startsNotResumed;  
  74.         boolean isForward;  
  75.         int pendingConfigChanges;  
  76.         boolean onlyLocalRequest;  
  77.   
  78.         View mPendingRemoveWindow;  
  79.         WindowManager mPendingRemoveWindowManager;  
  80.   
  81.         ...  
  82.     }  
  83.   
  84.   
  85.     private class ApplicationThread extends ApplicationThreadNative {  
  86.   
  87.         private void updatePendingConfiguration(Configuration config) {  
  88.             synchronized (mPackages) {  
  89.                 if (mPendingConfiguration == null ||  
  90.                         mPendingConfiguration.isOtherSeqNewer(config)) {  
  91.                     mPendingConfiguration = config;  
  92.                 }  
  93.             }  
  94.         }  
  95.   
  96.         public final void schedulePauseActivity(IBinder token, boolean finished,  
  97.                 boolean userLeaving, int configChanges) {  
  98.             queueOrSendMessage(  
  99.                     finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,  
  100.                     token,  
  101.                     (userLeaving ? 1 : 0),  
  102.                     configChanges);  
  103.         }  
  104.   
  105.         // we use token to identify this activity without having to send the  
  106.         // activity itself back to the activity manager. (matters more with ipc)  
  107.         public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,  
  108.                 ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,  
  109.                 Bundle state, List<ResultInfo> pendingResults,  
  110.                 List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,  
  111.                 String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {  
  112.             ActivityClientRecord r = new ActivityClientRecord();  
  113.   
  114.             r.token = token;  
  115.             r.ident = ident;  
  116.             r.intent = intent;  
  117.             r.activityInfo = info;  
  118.             r.compatInfo = compatInfo;  
  119.             r.state = state;  
  120.   
  121.             r.pendingResults = pendingResults;  
  122.             r.pendingIntents = pendingNewIntents;  
  123.   
  124.             r.startsNotResumed = notResumed;  
  125.             r.isForward = isForward;  
  126.   
  127.             r.profileFile = profileName;  
  128.             r.profileFd = profileFd;  
  129.             r.autoStopProfiler = autoStopProfiler;  
  130.   
  131.             updatePendingConfiguration(curConfig);  
  132.   
  133.             queueOrSendMessage(H.LAUNCH_ACTIVITY, r);  
  134.         }  
  135.   
  136.         ...  
  137.     }  
  138.   
  139.     private class H extends Handler {  
  140.   
  141.         public void handleMessage(Message msg) {  
  142.             if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));  
  143.             switch (msg.what) {  
  144.                 case LAUNCH_ACTIVITY: {  
  145.                     Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");  
  146.                     ActivityClientRecord r = (ActivityClientRecord)msg.obj;  
  147.   
  148.                     r.packageInfo = getPackageInfoNoCheck(  
  149.                             r.activityInfo.applicationInfo, r.compatInfo);  
  150.                     handleLaunchActivity(r, null);  
  151.                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);  
  152.                 } break;  
  153.                 ...  
  154.             }  
  155.             if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));  
  156.         }  
  157.          
  158.         ...  
  159.     }  
  160.   
  161.     public static ActivityThread currentActivityThread() {  
  162.         return sThreadLocal.get();  
  163.     }  
  164.   
  165.    
  166.     public static void main(String[] args) {  
  167.         SamplingProfilerIntegration.start();  
  168.   
  169.         // CloseGuard defaults to true and can be quite spammy.  We  
  170.         // disable it here, but selectively enable it later (via  
  171.         // StrictMode) on debug builds, but using DropBox, not logs.  
  172.         CloseGuard.setEnabled(false);  
  173.   
  174.         Environment.initForCurrentUser();  
  175.   
  176.         // Set the reporter for event logging in libcore  
  177.         EventLogger.setReporter(new EventLoggingReporter());  
  178.   
  179.         Process.setArgV0("<pre-initialized>");  
  180.   
  181.         Looper.prepareMainLooper();  
  182.   
  183.         // 创建ActivityThread实例  
  184.         ActivityThread thread = new ActivityThread();  
  185.         thread.attach(false);  
  186.   
  187.         if (sMainThreadHandler == null) {  
  188.             sMainThreadHandler = thread.getHandler();  
  189.         }  
  190.   
  191.         AsyncTask.init();  
  192.   
  193.         if (false) {  
  194.             Looper.myLooper().setMessageLogging(new  
  195.                     LogPrinter(Log.DEBUG, "ActivityThread"));  
  196.         }  
  197.   
  198.         Looper.loop();  
  199.   
  200.         throw new RuntimeException("Main thread loop unexpectedly exited");  
  201.     }  
  202. }  


4.2 家族图谱



4.3 ActivityThread内部类



4.4 ActivityThread工作流程

© 著作权归作者所有

下一篇: PHP笔记
思想永无止境
粉丝 4
博文 257
码字总数 292814
作品 0
昌平
程序员
私信 提问
Android插件化原理(一)Activity插件化

相关文章 Android深入四大组件系列 Android解析AMS系列 Android解析ClassLoader系列 前言 四大组件的插件化是插件化技术的核心知识点,而Activity插件化更是重中之重,Activity插件化主要有三...

刘望舒
2018/05/29
0
0
Android framework——Activity的启动和创建

本人制作的app:1号密码 欢迎试用   最近学习Android相关知识,感觉仅仅了解Activity几个生命周期函数基本上没有任何意义的; 于是想深入了解一下Activity到底是怎么一回事怎么运行来的;里...

jackxu2015
2015/08/14
0
0
Android插件化快速入门与实例解析(VirtualApk)必须了解一下

 集成一个第三方相册功能,只需集成一个插件APK到项目中,无需集成额外代码,并且支持随时更新相册功能,无需发布版本更新,无需AndroidManifest中声明四大组件,这就是插件化。   插件化...

android自学
2018/07/22
0
0
插件化之启动没有注册的Activity

启动没有在AndroidManifest中注册的Activity是安卓插件化中一个很重要的知识点,只有这样你才能把Activity中分离出来,放到插件中. 启动没有在AndroidManifest中注册的Activity,会涉及到Act...

嘉伟咯
2018/10/26
0
0
探索Activity启动流程-实现打开插件中的Activity

通过分析Activity的启动流程,探索Android的插件化,下面通过源码分析实现一个简单的插件化 打开一个 未安装apk中的Activity 开始分析 Activity的启动流程从 startActivity开始 然后通过 In...

liwg
2018/05/11
0
0

没有更多内容

加载失败,请刷新页面

加载更多

解决vim打开之后乱码的问题

在Windows中的文档,传输到Linux系统中(使用rz命令),出现乱码 root@localhost ~]# rpm -qf `which iconv` glibc-common-2.17-105.el7.x86_64 [root@localhost ~]# rpm -ihv /mnt/Packages......

寰宇01
13分钟前
0
0
aldi 2017年1月记录

../../tools/CBLAS/lib/cblas_LINUX.a ../../tools/lapack-3.4.2/liblapacke.a \../../tools/lapack-3.4.2/librefblas.a -lgfortran \../../tools/lapack-3.4.2/liblapack.a \../../......

MtrS
14分钟前
0
0
Choerodon如何进行日志收集与告警

作者:董文启 应用程序日志是由软件应用程序记录的事件文件, 它一般包含错误,信息事件和警告。一个良好的日志系统有助于快速发现问题,定位问题,同时也为业务分析起到一定的作用。 传统E...

Choerodon
26分钟前
1
0
js二维码生成插件“jquery.qrcode.min.js”

<!doctype html> <html> <head> <meta charset="utf-8" /> <title>生成二维码</title> <script type='text/javascript' src='http://cdn.staticfile.org/jquery/2.1.1/jquery.min.js'></scri......

泉天下
29分钟前
0
0
Spring AOP之同一个对象方法内部自调用导致事务失效问题

对于像我这种喜欢滥用AOP的程序员,遇到坑也是习惯了,不仅仅是事务,其实只要脱离了Spring容器管理的所有对象,对于SpringAOP的注解都会失效,因为他们不是Spring容器的代理类,SpringAOP,就切入不...

xiaomin0322
35分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部