首页 > 代码库 > Android ActivityThread(主线程或UI线程)简介
Android ActivityThread(主线程或UI线程)简介
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如下:
- 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如下:
- 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 类中关键信息
- /**
- * 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工作流程
Android ActivityThread(主线程或UI线程)简介