您的位置:首页 > 产品设计 > UI/UE

Android ActivityThread(主线程或UI线程)简介

2015-01-02 21:04 337 查看


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