您的位置:首页 > 其它

ActivityThread

2015-06-16 15:21 288 查看


ActivityThread运行框架

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

NaiveStart.main()

ZygoteInit.main

ZygoteInit$MethodAndArgsCall.run

Method.Invoke

method.invokeNative

ActivityThread.main()

Looper.loop()

....

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





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则是彻底的组件化思想构建,一开始的应用程序概念就是Activity,Service,Broadcast
receivers,ContentProvider,Intent,Task。这些概念体现了一个人机交互的模型本质:

界面呈现

发起请求,响应请求

内容交互

消息接收处理

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

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

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对象。该对象是activityThread和ActivityManagerService之间的桥梁。

在attach中还做了一件事情,就是通过代理调用attachApplication,并利用binder的transact机制,在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);

在客户端和服务端分别有一个管理activity的地方,服务端是在mHistory中,处于mHistory栈顶的就是当前处于running状态的activity,客户端是在mActivities中。
在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
plaincopy





at android.os.MessageQueue.nativePollOnce(Native Method)

at android.os.MessageQueue.next(MessageQueue.java:118)

at android.os.Looper.loop(Looper.java:118)

at android.app.ActivityThread.main(ActivityThread.java:4424) // Java main入口函数

at java.lang.reflect.Method.invokeNative(Native Method)

at java.lang.reflect.Method.invoke(Method.java:511)

at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)

at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)

at dalvik.system.NativeStart.main(Native Method)

JDWP线程stack如下:

[java] view
plaincopy





at org.apache.harmony.dalvik.ddmc.DdmVmInternal.getStackTraceById(Native Method)

at android.ddm.DdmHandleThread.handleSTKL(DdmHandleThread.java:131)

at android.ddm.DdmHandleThread.handleChunk(DdmHandleThread.java:77)

at org.apache.harmony.dalvik.ddmc.DdmServer.dispatch(DdmServer.java:171)

at dalvik.system.NativeStart.run(Native Method)


3. IApplicationThread关系图




4. ActivityThread类

ActivityThread类即代表Application主线程。


4.1 类中关键信息

[java] view
plaincopy





/**

* This manages the execution of the main thread in an

* application process, scheduling and executing activities,

* broadcasts, and other operations on it as the activity

* manager requests.

*

* {@hide}

*/

public final class ActivityThread {

static ContextImpl mSystemContext = null;

static IPackageManager sPackageManager;

// 创建ApplicationThread实例,以接收AMS指令并执行

final ApplicationThread mAppThread = new ApplicationThread();

final Looper mLooper = Looper.myLooper();

final H mH = new H();

final HashMap<IBinder, ActivityClientRecord> mActivities

= new HashMap<IBinder, ActivityClientRecord>();

// List of new activities (via ActivityRecord.nextIdle) that should

// be reported when next we idle.

ActivityClientRecord mNewActivities = null;

// Number of activities that are currently visible on-screen.

int mNumVisibleActivities = 0;

final HashMap<IBinder, Service> mServices

= new HashMap<IBinder, Service>();

Application mInitialApplication;

final ArrayList<Application> mAllApplications

= new ArrayList<Application>();

static final ThreadLocal<ActivityThread> sThreadLocal = new ThreadLocal<ActivityThread>();

Instrumentation mInstrumentation;

static Handler sMainThreadHandler; // set once in main()

static final class ActivityClientRecord {

IBinder token;

int ident;

Intent intent;

Bundle state;

Activity activity;

Window window;

Activity parent;

String embeddedID;

Activity.NonConfigurationInstances lastNonConfigurationInstances;

boolean paused;

boolean stopped;

boolean hideForNow;

Configuration newConfig;

Configuration createdConfig;

ActivityClientRecord nextIdle;

String profileFile;

ParcelFileDescriptor profileFd;

boolean autoStopProfiler;

ActivityInfo activityInfo;

CompatibilityInfo compatInfo;

LoadedApk packageInfo; //包信息,通过调用ActivityThread.getPapckageInfo而获得

List<ResultInfo> pendingResults;

List<Intent> pendingIntents;

boolean startsNotResumed;

boolean isForward;

int pendingConfigChanges;

boolean onlyLocalRequest;

View mPendingRemoveWindow;

WindowManager mPendingRemoveWindowManager;

...

}

private class ApplicationThread extends ApplicationThreadNative {

private void updatePendingConfiguration(Configuration config) {

synchronized (mPackages) {

if (mPendingConfiguration == null ||

mPendingConfiguration.isOtherSeqNewer(config)) {

mPendingConfiguration = config;

}

}

}

public final void schedulePauseActivity(IBinder token, boolean finished,

boolean userLeaving, int configChanges) {

queueOrSendMessage(

finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,

token,

(userLeaving ? 1 : 0),

configChanges);

}

// we use token to identify this activity without having to send the

// activity itself back to the activity manager. (matters more with ipc)

public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,

ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,

Bundle state, List<ResultInfo> pendingResults,

List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,

String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {

ActivityClientRecord r = new ActivityClientRecord();

r.token = token;

r.ident = ident;

r.intent = intent;

r.activityInfo = info;

r.compatInfo = compatInfo;

r.state = state;

r.pendingResults = pendingResults;

r.pendingIntents = pendingNewIntents;

r.startsNotResumed = notResumed;

r.isForward = isForward;

r.profileFile = profileName;

r.profileFd = profileFd;

r.autoStopProfiler = autoStopProfiler;

updatePendingConfiguration(curConfig);

queueOrSendMessage(H.LAUNCH_ACTIVITY, r);

}

...

}

private class H extends Handler {

public void handleMessage(Message msg) {

if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));

switch (msg.what) {

case LAUNCH_ACTIVITY: {

Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");

ActivityClientRecord r = (ActivityClientRecord)msg.obj;

r.packageInfo = getPackageInfoNoCheck(

r.activityInfo.applicationInfo, r.compatInfo);

handleLaunchActivity(r, null);

Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

} break;

...

}

if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));

}

...

}

public static ActivityThread currentActivityThread() {

return sThreadLocal.get();

}

public static void main(String[] args) {

SamplingProfilerIntegration.start();

// CloseGuard defaults to true and can be quite spammy. We

// disable it here, but selectively enable it later (via

// StrictMode) on debug builds, but using DropBox, not logs.

CloseGuard.setEnabled(false);

Environment.initForCurrentUser();

// Set the reporter for event logging in libcore

EventLogger.setReporter(new EventLoggingReporter());

Process.setArgV0("<pre-initialized>");

Looper.prepareMainLooper();

// 创建ActivityThread实例

ActivityThread thread = new ActivityThread();

thread.attach(false);

if (sMainThreadHandler == null) {

sMainThreadHandler = thread.getHandler();

}

AsyncTask.init();

if (false) {

Looper.myLooper().setMessageLogging(new

LogPrinter(Log.DEBUG, "ActivityThread"));

}

Looper.loop();

throw new RuntimeException("Main thread loop unexpectedly exited");

}

}


4.2 家族图谱




4.3 ActivityThread内部类



4.4 ActivityThread工作流程
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: