Android ActivityThread 主執行緒或UI執行緒 簡介
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow
也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!
1. ActivityThread功能
它管理應用程序的主執行緒的執行(相當於普通Java程式的main入口函式),並根據AMS的要求(通過IApplicationThread介面,AMS為Client、ActivityThread.ApplicationThread為Server)負責排程和執行
在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工作流程