ActivityThread

ActivityThread运行框架

在分析中,我们可以看到真正对应应用进程的不是Application而是ActivityThread。我们从实际的应用堆栈可以看到:

NaiveStart.main()

        ZygoteInit.main

           ZygoteInit$MethodAndArgsCall.run

              Method.Invoke

                                       method.invokeNative

                     ActivityThread.main()

                         Looper.loop()

                                                                 ....

 每个应用程序都以ActivityThread.main()为入口进入到消息循环处理。对于一个进程来讲,我们需要这个闭合的处理框架。

image

ActivitiyThread是应用程序概念空间的重要概念,他建立了应用进程运行的框架,并提供了一个IActivityThread接口作为与 Activity Manager Service的通讯接口.通过该接口AMS可以将Activity的状态变化传递到客户端的Activity对象。


以前一直都说Activity的人口是onCreate方法。其实android上一个应用的入口,应该是ActivityThread。和普通的java类一样,入口是一个main方法。

public static final void main(String[] args) {
        SamplingProfilerIntegration.start();
       ……
        Looper.prepareMainLooper();
        if (sMainThreadHandler == null) {
            sMainThreadHandler = new Handler();
        }
        ActivityThread thread = new ActivityThread();
        thread.attach(false);
       ……
        Looper.loop();
       ……
        thread.detach();
        ……
        Slog.i(TAG, "Main thread of " + name + " is now exiting");
    }

下面仔细分析一下这个main方法。


2.Looper.prepareMainLooper();

ActivityThread其实就是我们经常说的UI thread,也就是主线程。我们都知道主线程可以使用Handler进行异步通信,因为主线程中已经创建了Looper,而这个Looper就是在这里创建的。如果其他线程需要使用Handler通信,就要自己去创建Looper。


3. sMainThreadHandler = new Handler();

创建一个Handler。


4. ActivityThread thread = new ActivityThread();

创建ActivityThread 对象。

ActivityThread 有几个比较重要的成员变量,会在创建ActivityThread对象时初始化。

(1)final ApplicationThread mAppThread = new ApplicationThread();

ApplicationThread继承自ApplicationThreadNative, 而ApplicationThreadNative又继承自Binder并实现了IApplicationThread接口。IApplicationThread继承自IInterface。这是一个很明显的binder结构,用于于Ams通信。IApplicationThread接口定义了对一个程序(linux的进程)操作的接口。ApplicationThread通过binder与Ams通信,并将Ams的调用,通过下面的H类(也就是Hnalder)将消息发送到消息队列,然后进行相应的操作,入activity的start, stop。

(2)final H mH = new H();

          private final class H extends Handler

mH负责处理ApplicationThread发送到消息队列的消息,例如:

public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + msg.what);
            switch (msg.what) {
                case LAUNCH_ACTIVITY: {
                    ActivityClientRecord r = (ActivityClientRecord)msg.obj;

                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo);
                    handleLaunchActivity(r, null);
                } break;


5. handleLaunchActivity(r, null);

从名字中就可以看出,这里就将进行启动activity的工作了。

方法中主要调用了这一句:

Activity a = performLaunchActivity(r, customIntent);


6. performLaunchActivity()

进行了一些初始化和赋值操作后,创建activity。

activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);

然后调用:

mInstrumentation.callActivityOnCreate(activity, r.state);

这一句就会调用到acitivity的onCreate方法了,就进入了大多数应用开发的入口了。


在阅读SDK文档和研究Activity这个概念时,我感觉到了Android中若隐若现的Android自由无边界这个设计意图Android的应用只是一个虚的概念,并没有实际的入口,这个不像Window平台上的应用程序的概念,Android更多的是提供组件(Components)的概念。为什么要虚化应用的概念?我想这个虚化就是自由无边界设计意图的直接体现。突出请求和服务,突出组件个体,弱化边界,系统的各个组件可以自由的无边界的交流,服务请求者直接发出请求,不论这个对象在何处和属于谁的,组件是自由独立的个体,一个应用程序可以直接请求使用其他的应用的的组件,这个是Android应用框架设计的核心理念,其他的一切都是在为这个核心理念服务。


让程序员忽略应用的概念,甚至彻底的抛弃进程这样的概念,程序员看到的就是一个一个的组件,应用程序员利用这些组件来架构成一个所谓的应用,那么设计者首先要考虑的是什么呢?我想应该是一个抽象的应用模型,在这个模型下产生概念和接口。


Android则是彻底的组件化思想构建,一开始的应用程序概念就是ActivityService,Broadcast receiversContentProvider,IntentTask。这些概念体现了一个人机交互的模型本质:

界面呈现

发起请求,响应请求

内容交互

消息接收处理

 

ActivityAndroid应用的核心概念,简而言之Activity为用户交互管理者,有一个可视界面呈现,而ServiceActivity的区别是他在后台运行,没有界面呈现。而Intent的意义是意图,他在Android的概念空间中,代表消息,这个消息代表了请求的意图。

Activity可以到处存在,提供服务,消除空间差别,Activity是一个独立的个体,更能表现面向对象的实质。这个个体需要接受另外的个体的消息,可以随时发起对另外一个个体的请求。个体是自由的,Android中你可以开始一个Activity,但是没有权利消灭一个Activity,这是个体权利的体现,个体的消灭是由系统决定的,这个就是AndroidActivity蕴含的人文意义。


ActivityThread:

ActivityThread主要用来启动应用程序的主线程,并且管理在应用端跟用户打交道的activity。在应用端的activity信息全部被存储在ActivityThread的成员变量mActivities中。

final HashMap<IBinder, ActivityRecord> mActivities= new  HashMap<IBinder, ActivityRecord>(); 


也就是说,在mActivities中,记录了应用程序创建的所有activity实例记录,对应的是ActivityRecord

ActivityThread是怎么启动应用程序的呢?ActivityThread中有一个main函数,在这个里面,将启动应用程序并建立消息循环。在之前也介绍过,系统会为主线程自动创建消息循环。


每个应用程序对应着一个ActivityThread实例,应用程序由ActivityThread.main打开消息循环。每个应用程序同时也对应着一个ApplicationThread对象。该对象是activityThreadActivityManagerService之间的桥梁。

attach中还做了一件事情,就是通过代理调用attachApplication,并利用bindertransact机制,在ActivityManagerService中建立了ProcessRecord信息。


ActivityManagerService和ActivityStack位于同一个进程中,而ApplicationThread和ActivityThread位于另一个进程中,这个就要看代码,后面有两篇文章可以参考:《Android应用程序进程启动过程的源代码分析》和《Android系统进程Zygote启动过程的源代码分析》。
Zygote进程启动System进程->System进程创建一个线程来启动ActivityManagerService->ActivityManagerService内部又会创建一个ActivityStack来维护系统的Activity组件堆栈。
ActivityManagerService请求Zygote进程创建一个应用程序进程->应用程序进程加载一个ActivityThread实例->ActivityThread实例在内部创建一个ApplicationThread实例,用来和ActivityManagerService通信。




客户端保存的Activities是ActivityRecord的形式,是放在ActivityThread的mAcitivities中的,一个应用一个ActivityThead.
ActivityStack::realStartActivityLocked()
->app.thread.scheduleLaunchActivity() --- ProcessRecord.IApplicationThread::scheduleL...
->ApplicationThread::scheduleLaunchActivity()
->ActivityThread::handleMessage() case LAUNCH_ACTIVITY
->ActivityThread::handleLaunchActivity(r, null)
->ActivityThread:: performLaunchActivity() --- mActivities.put(r.token, r);
服务端
AMS::startHomeActivityLocked()
->ActivityStack::startActivityLocked() --- mHistory.add(addPos, r);


  1. 在客户端和服务端分别有一个管理activity的地方,服务端是在mHistory中,处于mHistory栈顶的就是当前处于running状态的activity,客户端是在mActivities中。
  2. startActivity时,首先会在ActivityManagerService中建立HistoryRecord,并加入到mHistory中,然后通过scheduleLaunchActivity在客户端创建ActivityRecord记录并加入到mActivities中。最终在ActivityThread发起请求,进入消息循环,完成activity的启动和窗口的管理等

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工作流程


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值