1. 程式人生 > >Android ActivityThread 主執行緒或UI執行緒 簡介

Android ActivityThread 主執行緒或UI執行緒 簡介

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

               

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








           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述