Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 四大組件的工作過程探索(一)

四大組件的工作過程探索(一)

編輯:關於Android編程

四大組件的運行狀態:


Android中的四大組件中除了BroadcastReceiver以外,其他三種組件都必須在Android Mainfrst中注冊。對於,BroadcastReceiver來說,他既可以在AndroidMainfrst中注冊也可以通過代碼來注冊。在調用方式上,Activity,Service和BroadcastReceiver需要借助Intent,而ContentProvider則無需借助Intent。

Activity的工作過程:

為了方便日常的開發工作,系統對四大組件的工作過程進行了很大程度的封裝,這使得開發者無需關注實現細節即可快速的使用四大組件。Activity作為很重要的一個組件,其內部工作過程系統當然也是做了很多的封裝,這種封裝使得啟動一個Activity變得異常的簡單。在顯示調用的情形下,只需要通過如下代碼即可完成:
Intent intent=new Intent(this,TestActivity.class);
startActivity(intent);

通過上面的代碼即可啟動一個具體的activity,然後新Activity就會被系統啟動並展示在 用戶的眼前,這個過程對於Android開發者來說最普通不過了,這也是很理所當然的事情,但是有沒有想過系統內部到底是如何啟動一個Activity的呢?下面我們就來介紹一下。
注意一點:在研究內部實現上應該更加側重於對整體流程的把握,而不能深入代碼細節不能自拔,太深入代碼細節往往會導致越看越迷茫的撞到。無法對整體流程建立足夠的認識,取而代之的是繁瑣的細節。但是代碼的細節本身不具有太多的指導意義,因此這種學習狀態是要極力避免的。所以本博客會側重於對Activity工作過程的分析整體流程。
我們從Acitivity的startActivity的方法開始分析,startActivity的方法有好幾種重載方式,但是他們最終都會調用startActivityForResult方法,實現如下:
public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
        if (mParent == null) {
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
            if (ar != null) {
                mMainThread.sendActivityResult(
                    mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                    ar.getResultData());
            }
            if (requestCode >= 0) {
                // If this start is requesting a result, we can avoid making
                // the activity visible until the result is received.  Setting
                // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the
                // activity hidden during this time, to avoid flickering.
                // This can only be done when a result is requested because
                // that guarantees we will get information back when the
                // activity is finished, no matter what happens to it.
                mStartedActivity = true;
            }
        } else {
            if (options != null) {
                mParent.startActivityFromChild(this, intent, requestCode, options);
            } else {
                // Note we want to go through this method for compatibility with
                // existing applications that may have overridden it.
                mParent.startActivityFromChild(this, intent, requestCode);
            }
        }
    }

在上面的代碼中,我們只需要關注mParent==null這部分邏輯,mParent代表的是ActivityGroup,ActivityGroup最開始被用來在一個界面中嵌入多個子Activity,但是其在API13中已經被廢棄了,系統推薦采用Fragment來代替ActivityGroup,Fragment的好處就不多說了、在上面的代碼中需要注意mMainThread.getApplicationThread()這個參數,他的類型是ApplicationThread,ApplicationThread是ActivityThread在Activity的啟動過程中發揮著很重要的作用。接著看一下Instrumentation的execStartActiivty方法。如下所示:
 public ActivityResult execStartActivity(
            Context who, IBinder contextThread, IBinder token, Activity target,
            Intent intent, int requestCode, Bundle options) {
        IApplicationThread whoThread = (IApplicationThread) contextThread;
        if (mActivityMonitors != null) {
            synchronized (mSync) {
                final int N = mActivityMonitors.size();
                for (int i=0; i= 0 ? am.getResult() : null;
                        }
                        break;
                    }
                }
            }
        }
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess();
            int result = ActivityManagerNative.getDefault()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target != null ? target.mEmbeddedID : null,
                        requestCode, 0, null, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
        }
        return null;
    }


從上面的代碼來看,啟動Actiivty真正的實現由ActivityManagerNative.getDefault()的startActivity方法完成。ActivityManagerService(簡稱AMS)繼承自Binder並實現了IActivityManager這個Binder接口,因此AMS也是一個Binder,他是IActivityManager的具體實現。由於ActivityManagerNative.getDefault()其實是一個IActivityManager類型的Binder對象,因此他的具體實現是AMS。可以發現,在ActivityManagerNative中。AMS這個Binder對象采用單例模式對外提供,Singleton是一個單利的封裝類,第一次調用它的get方法時他會通過create方法來初始化AMS這個Binder對象,在後續的調用中則直接返回之前創建的對象,源碼如下:
static public IActivityManager More ...getDefault() {
          return gDefault.get();
      }

private static final Singleton gDefault = new Singleton() {
        protected IActivityManager More ...create() {
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
           }
            return am;
        }
    };

再附上ActivityManagerNative的完整源碼地址:源碼,有興趣的可以去閱讀一下。 從上面的分析可以知道,Activity由ActivityManagerNative.getDefault()來啟動。而ActivityManagerNative.getDefault()實際上是AMS,因此Activity的啟動過程又轉移到了AMS中,為了繼續分析這個過程,只需要查看AMS的startActivity方法即可,在分析AMS的startActivity方法之前,我們先回過頭來看一下Instrumentation的execStartActivity方法,其中有一行代碼:checkStartActivityResult(result,intent),直觀上看起來這個方法的作用像是在檢查啟動Activity的記過,他的具體實現如下所示:
/*package*/ static void checkStartActivityResult(int res, Object intent) {
        if (res >= ActivityManager.START_SUCCESS) {
            return;
        }
        
        switch (res) {
            case ActivityManager.START_INTENT_NOT_RESOLVED:
            case ActivityManager.START_CLASS_NOT_FOUND:
                if (intent instanceof Intent && ((Intent)intent).getComponent() != null)
                    throw new ActivityNotFoundException(
                            "Unable to find explicit activity class "
                            + ((Intent)intent).getComponent().toShortString()
                            + "; have you declared this activity in your AndroidManifest.xml?");
                throw new ActivityNotFoundException(
                        "No Activity found to handle " + intent);
            case ActivityManager.START_PERMISSION_DENIED:
                throw new SecurityException("Not allowed to start activity "
                        + intent);
            case ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT:
                throw new AndroidRuntimeException(
                        "FORWARD_RESULT_FLAG used while also requesting a result");
            case ActivityManager.START_NOT_ACTIVITY:
                throw new IllegalArgumentException(
                        "PendingIntent is not an activity");
            default:
                throw new AndroidRuntimeException("Unknown error code "
                        + res + " when starting " + intent);
        }
    }
從上面的代碼可以看出,checkStartActivityResult的作用很明顯,就是檢查啟動Activity的結果,當無法正確啟動一個Activity時,這個方法會拋出異常信息,其中最熟悉不過的就是"unable to find expliit activity class; have you declared this activity in your androidmainfest.xml"這個異常我就不說了,你懂的。
接著我們繼續分析AMS的startActivity方法,如下所示:
public final int More ...startActivity(IApplicationThread caller, String callingPackage,
             Intent intent, String resolvedType, IBinder resultTo,
             String resultWho, int requestCode, int startFlags,
             String profileFile, ParcelFileDescriptor profileFd, Bundle options) {
         return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                 resultWho, requestCode,
                 startFlags, profileFile, profileFd, options, UserHandle.getCallingUserId());
     }
public final int More ...startActivityAsUser(IApplicationThread caller, String callingPackage,
             Intent intent, String resolvedType, IBinder resultTo,
             String resultWho, int requestCode, int startFlags,
             String profileFile, ParcelFileDescriptor profileFd, Bundle options, int userId) {
         enforceNotIsolatedCaller("startActivity");
         userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
                 false, true, "startActivity", null);
         return mMainStack.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType,
                 resultTo, resultWho, requestCode, startFlags, profileFile, profileFd,
                 null, null, options, userId);
     }

可以看出,Activity的啟動過程又轉移到了ActivityStackSupervisor的startActivityMayWait方法中了。在startActivityMayWait中又調用了startActivityLocked方法,接著startActivityLocked又調用了ActivityStack的resumeTopActivityiesLocked方法,這個時候啟動過程已經從ActivityStackSupervisor轉移到了ActivityStack。
ActivityStack的resumeTopActivitiesLocked方法的實現如下所示:
final boolean More ...resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
        if (inResumeTopActivity) {
            // Don't even start recursing.
            return false;
        }

        boolean result = false;
        try {
            // Protect against recursion.
            inResumeTopActivity = true;
            result = resumeTopActivityInnerLocked(prev, options);
        } finally {
            inResumeTopActivity = false;
        }
        return result;
    }

從上面的代碼可以看出,resumeTopActivityLocked調用了resumeTopActivityInnerLocked方法,resumeTopActivityInnerLocked方法又調用了ActivityStackSupervisor的satrtSpecificActivityLocked方法,satrtSpecificActivityLocked的源碼如下:
void More ...startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        // Is this activity's application already running?
        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                r.info.applicationInfo.uid, true);

        r.task.stack.setLaunchTime(r);

        if (app != null && app.thread != null) {
            try {
                if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                        || !"android".equals(r.info.packageName)) {
                    // Don't add this if it is a platform component that is marked
                    // to run in multiple processes, because this is actually
                    // part of the framework so doesn't make sense to track as a
                    // separate apk in the process.
                    app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
                            mService.mProcessStats);
                }
                realStartActivityLocked(r, app, andResume, checkConfig);
                return;
            } catch (RemoteException e) {
                Slog.w(TAG, "Exception when starting activity "
                        + r.intent.getComponent().flattenToShortString(), e);
            }

            // If a dead object exception was thrown -- fall through to
            // restart the application.
        }

        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                "activity", r.intent.getComponent(), false, false, true);
    }

從上面的代碼可以看出,satrtSpecificActivityLocked方法調用了realStartActivityLocked方法,為了更清晰的說明Activity的啟動過程在ActivityStatckSupervisor和ActivityStack之間的傳遞順序,下面給出一張流程圖。

\


在ActivityStackSupervisZ喎?/kf/ware/vc/" target="_blank" class="keylink">vcrXEcmVhbFN0YXJ0QWN0aXZpdHlMb2NrZWS3vbeo1tAg09bI58/CINK7ts60+sLro7o8L2Rpdj4KPGRpdj48YnI+CjwvZGl2Pgo8ZGl2PjxwcmUgY2xhc3M9"brush:java;"> app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken, System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration), r.compat, r.task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results, newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
這段代碼很重要,其中app.thread的類型為IApplicationThread,IApplicationThread的聲明如下:
查看源碼
因為他繼承了IInterface接口,所以他是一個Binder類型的接口,從IApplicationThread聲明的接口方法中可以看出,其內部包含了大量啟動,停止Activity 的接口,此外還包含了啟動和停止服務的接口,從接口的方法的命名可以猜測,IApplicationThread這個Binder接口的實現者完成了大量和Activity以及Service啟動停止相關的功能。
那麼IApplicationThread的實現者到底是什麼?答案就是ActivityThread中的內部類ApplicationThread,洗面來看ApplicationThread的定義:
 private class More ...ApplicationThread extends ApplicationThreadNative

public abstract class More ...ApplicationThreadNative extends Binder
          implements IApplicationThread 
可以看出,ApplicationThread繼承了ApplicationThreadNative,而ApplicationThreadNative則繼承了Binder並實現了IApplicationThread接口。如果讀者還記得系統的AIDL文件自動生成的代碼,就會發現ApplicationThreadNative的作用其實和系統為AIDL文件生成的類是一樣的。
在ApplicationThreadNative的內部,還有一個ApplicationThreadProxy類,這個類的實現如下所示,其實這個內部類也是系統為AIDL文件自動生成的代理類。所以ApplicationThreadNative就是IApplicationThread的實現者,由於ApplicationThreadNative被系統定義為抽象類,所以ApplicationThread就成了IApplicationThread的最終實現者了。
class More ...ApplicationThreadProxy implements IApplicationThread {
     private final IBinder mRemote;
     
     public More ...ApplicationThreadProxy(IBinder remote) {
         mRemote = remote;
     }
     
     public final IBinder More ...asBinder() {
         return mRemote;
     }
     
     public final void More ...schedulePauseActivity(IBinder token, boolean finished,
             boolean userLeaving, int configChanges, boolean dontReport) throws RemoteException {
         Parcel data = Parcel.obtain();
         data.writeInterfaceToken(IApplicationThread.descriptor);
         data.writeStrongBinder(token);
         data.writeInt(finished ? 1 : 0);
         data.writeInt(userLeaving ? 1 :0);
         data.writeInt(configChanges);
         data.writeInt(dontReport ? 1 : 0);
         mRemote.transact(SCHEDULE_PAUSE_ACTIVITY_TRANSACTION, data, null,
                 IBinder.FLAG_ONEWAY);
         data.recycle();
     }
 
     public final void More ...scheduleStopActivity(IBinder token, boolean showWindow,
             int configChanges) throws RemoteException {
         Parcel data = Parcel.obtain();
         data.writeInterfaceToken(IApplicationThread.descriptor);
         data.writeStrongBinder(token);
         data.writeInt(showWindow ? 1 : 0);
         data.writeInt(configChanges);
         mRemote.transact(SCHEDULE_STOP_ACTIVITY_TRANSACTION, data, null,
                 IBinder.FLAG_ONEWAY);
         data.recycle();
     }
...
}
繞了一大圈,Activity的啟動過程最終回到了ApplicationThread中,ApplicationThread通過scheduleLaunchActivity方法來啟動Activity,代碼如下:
public final void More ...scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                 ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
                 IVoiceInteractor voiceInteractor, int procState, Bundle state,
                 PersistableBundle persistentState, List pendingResults,
                 List pendingNewIntents, boolean notResumed, boolean isForward,
                 ProfilerInfo profilerInfo) {
 
             updateProcessState(procState, false);
 
             ActivityClientRecord r = new ActivityClientRecord();
 
             r.token = token;
             r.ident = ident;
             r.intent = intent;
             r.voiceInteractor = voiceInteractor;
             r.activityInfo = info;
             r.compatInfo = compatInfo;
             r.state = state;
             r.persistentState = persistentState;
 
             r.pendingResults = pendingResults;
             r.pendingIntents = pendingNewIntents;
 
             r.startsNotResumed = notResumed;
             r.isForward = isForward;
 
             r.profilerInfo = profilerInfo;
 
             updatePendingConfiguration(curConfig);
 
             sendMessage(H.LAUNCH_ACTIVITY, r);
        }

接下來看一下Handler H對消息的處理,如下所示:
private class More ...H extends Handler {
        public static final int LAUNCH_ACTIVITY         = 100;
        public static final int PAUSE_ACTIVITY          = 101;
        public static final int PAUSE_ACTIVITY_FINISHING= 102;
        public static final int STOP_ACTIVITY_SHOW      = 103;
        public static final int STOP_ACTIVITY_HIDE      = 104;
        public static final int SHOW_WINDOW             = 105;
        public static final int HIDE_WINDOW             = 106;
       public static final int RESUME_ACTIVITY         = 107;
public void More ...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");
                    final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    handleLaunchActivity(r, null);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
                case RELAUNCH_ACTIVITY: {
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityRestart");
                    ActivityClientRecord r = (ActivityClientRecord)msg.obj;
                    handleRelaunchActivity(r);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
                case PAUSE_ACTIVITY:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
                    handlePauseActivity((IBinder)msg.obj, false, (msg.arg1&1) != 0, msg.arg2,
                            (msg.arg1&2) != 0);
                    maybeSnapshot();
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                   break;
....
}
 if (DEBUG_MESSAGES) Slog.v(TAG, "<<< done: " + codeToString(msg.what));
}

從Handler H對“LAUNCH_ACTIVITY”這個消息的處理可以知道,Activity的啟動過程 由ActivityThread的handleLaunchActivity方法實現,他的源碼如下:
private void handleLaunceActivity(ActivityClientRecord r,Iintent customIntent){
...
if(localLOGV)Slog.v(TAG,"Handling launch of"+r);

Activity a=performLaunchActivity(r,customIntent);

if(a!=null){
r.createdConfig=new Configuration(mConfiguration);
Bundle oldState=r.statr;
handleResumeActivity(r.token,false,r.isForward,!r.activity.mFinished&&!r. startsNotResumed);
...
}
...
}
從上面的源碼可以看出,perforLaunchActivity方法最終完成了Activity對象的創建和啟動過程,並且ActivityThread通過handleResumeActivity方法來調用被啟動Activity的onResume這以生命周期方法。
perforLaunchActivity這個方法主要完成了如下幾件事情:

1.從ActivityClientRecord中獲取待啟動的Activity的組件信息。


ActivityInfo aInfo = r.activityInfo;
        if (r.packageInfo == null) {
            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                    Context.CONTEXT_INCLUDE_CODE);
        }

        ComponentName component = r.intent.getComponent();
        if (component == null) {
            component = r.intent.resolveActivity(
                mInitialApplication.getPackageManager());
            r.intent.setComponent(component);
        }

        if (r.activityInfo.targetActivity != null) {
           component = new ComponentName(r.activityInfo.packageName,
                    r.activityInfo.targetActivity);
        }

2.通過Instrumentation的newActivity方法使用類加載器創建Activity對象:

Activity activity = null;
        try {
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to instantiate activity " + component
                    + ": " + e.toString(), e);
            }
        }

至於Instrumentation的newActivity,他的實現比較簡單,就是通過類加載器來創建Activity對象:
public Activity More ...newActivity(ClassLoader cl, String className,
            Intent intent)
            throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {
        return (Activity)cl.loadClass(className).newInstance();
    }

3,通過LoadedApk的makeApplication方法來嘗試創建Application對象:


public Application More ...makeApplication(boolean forceDefaultAppClass,
             Instrumentation instrumentation) {
         if (mApplication != null) {
             return mApplication;
         }
 
         Application app = null;
 
         String appClass = mApplicationInfo.className;
         if (forceDefaultAppClass || (appClass == null)) {
             appClass = "android.app.Application";
         }
 
         try {
             java.lang.ClassLoader cl = getClassLoader();
             if (!mPackageName.equals("android")) {
                 initializeJavaContextClassLoader();
             }
             ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
             app = mActivityThread.mInstrumentation.newApplication(
                     cl, appClass, appContext);
             appContext.setOuterContext(app);
         } catch (Exception e) {
             if (!mActivityThread.mInstrumentation.onException(app, e)) {
                 throw new RuntimeException(
                     "Unable to instantiate application " + appClass
                     + ": " + e.toString(), e);
             }
         }
         mActivityThread.mAllApplications.add(app);
         mApplication = app;
 
         if (instrumentation != null) {
             try {
                 instrumentation.callApplicationOnCreate(app);
             } catch (Exception e) {
                 if (!instrumentation.onException(app, e)) {
                     throw new RuntimeException(
                         "Unable to create application " + app.getClass().getName()
                         + ": " + e.toString(), e);
                 }
             }
         }

從makeApplication的實現可以看出,如果Application已經被創建過了,那麼就不會再重復創建了,這也意味著一個應用只有一個Application對象,Application對象的創建也是通過Instrumentation來完成,這個過程和Activity的創建一樣,都是通過類加載器來實現的,Application創建完畢後,系統會通過Instrumentation的callApplicationOnCreate來調用Application的onCreate方法。

4.創建ContextImpl對象並通過Activity的attach方法來完成一些重要的數據初始化:



ContextImpl是一個很重要的數據結構,他是Context的具體實現,Context中的大部分邏輯都是由ContextImpl來完成的。ContxetImpl是通過Activity的attach的方法和Activity建立關聯的,除此之外,在attach方法中Activity還會完成Window的創建並建立自己和Window的關聯,這樣當Window接受到外部輸入事件後,就可以將事件傳遞給Acivity

5.調用Activity的onCreate方法


mInstrumentation。callActivityOnCreate(activity,r.state),由於Activity的onCreate已經被調用,這也意味著Activity已經完成了整個啟動過程。



  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved