Android Activity啟動(dòng)流程(基于Android8.0系統(tǒng))

主要對(duì)象介紹

  • ActivityManagerService:負(fù)責(zé)系統(tǒng)中所有Activity的生命周期捂寿;
  • ActivityThread:App的真正入口刹泄,當(dāng)App啟動(dòng)后诊胞,會(huì)調(diào)用其main方法開始執(zhí)行庸队,開啟消息循環(huán)隊(duì)列刁卜。是傳說中的UI線程软瞎,即主線程逢唤。與ActivityManagerService配合,一起完成Activity的管理工作涤浇;
  • ApplicationThread:用來實(shí)現(xiàn)ActivityManagerService與ActivityThread之間的交互鳖藕。在ActivityManagerService需要管理相關(guān)Application中的Activity的生命周期,通過ApplicationThread的代理對(duì)象與ActivityThread通訊只锭;
  • ApplictationThreadProxy:是ApplicationThread在服務(wù)端的代理對(duì)象著恩,負(fù)責(zé)和客戶端的ApplicationThread通訊。AMS就是通過這個(gè)代理對(duì)象與ActivityThread進(jìn)行通信的蜻展,Android 8.0上以刪除該類喉誊,采用AIDL接口的方式來進(jìn)行IPC,實(shí)現(xiàn)RPC操作纵顾;
  • Instrumentation:每一個(gè)應(yīng)用程序都只有一個(gè)Instrumentation對(duì)象伍茄,每個(gè)Activity內(nèi)都有一個(gè)對(duì)該對(duì)象的引用。Instrumentation可以理解為應(yīng)用進(jìn)程的管家施逾,ActivityThread要?jiǎng)?chuàng)建或者打開某個(gè)Activity時(shí)敷矫,都需要通過Instrumentation來進(jìn)行具體的操作;
  • ActvitityStack:Activity在AMS的棧管理汉额,用來記錄已經(jīng)啟動(dòng)的Activity的先后關(guān)系曹仗、狀態(tài)信息等。通過ActivityStack決定是否需要啟動(dòng)新的進(jìn)程蠕搜;
  • ActivityRecord:ActivityStatck的管理對(duì)象怎茫,每個(gè)Activity在AMS對(duì)應(yīng)的一個(gè)ActivityRecord,來記錄Activity的狀態(tài)以及其他信息讥脐≡饩樱可以理解為Activity在服務(wù)端的Activity對(duì)象的映射;
  • ActivityClientRecord:與ActivityRecord是在服務(wù)端(AMS)的記錄相對(duì)應(yīng)旬渠,是Activity在客戶端(ActivityThread)的記錄俱萍;
  • TaskRecord:AMS抽象出來的任務(wù)棧的概念。一個(gè)TaskRecord包含若干個(gè)ActivityRecord告丢。ASM用它來確保Activity啟動(dòng)和退出順序枪蘑。它與Activity的啟動(dòng)模式直接相關(guān)。
  • ActivityStarter:啟動(dòng)Activity的控制器,主要用于用來將Intent和flags轉(zhuǎn)換成activity和相關(guān)任務(wù)棧岳颇;
  • ActivityStackSupervisor:主要管理著mHomeStack和mFocusedStack兩個(gè)ActivityStack等相關(guān)信息照捡;

Binder通信

  • 在Android 8.0以前,Binder通信的流程如下:
    客戶端: ActivityManagerProxy -> Binder驅(qū)動(dòng) -> 服務(wù)端:ActivityManagerService
    服務(wù)端: ApplicationThreadProxy -> Binder驅(qū)動(dòng) -> 客戶端:ApplicationThread
  • Android8.0開始话侧,刪除了ActivityManagerNative栗精,AMS的繼承類也發(fā)生了變化,繼承了IActivityManager.Stub接口類瞻鹏。了解Android的Binder機(jī)制應(yīng)該知道悲立,這里IActivityManager.aidl生成的接口類。Android8.0開始新博,把一些Binder代碼轉(zhuǎn)化為了AIDL模板方式:
public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback

ActivityManager中的代碼:

    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }

    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };
  • 而在Android7.0及其以前的版本上,則是客戶端通過ActivityManaagerProxy與服務(wù)端的ActivityManager進(jìn)行通信的
    ActivityManagerNative:
**
*獲得IActivityManager類
*/
static public IActivityManager getDefault() {
        return gDefault.get();
    }

static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }
 
        return new ActivityManagerProxy(obj);

}

ActivityManager:

private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager 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;
        }
};

可以看出來薪夕,兩個(gè)寫法不一樣,本質(zhì)上都是一樣的赫悄,Android 8.0可能使用了AIDL方式進(jìn)行ipc原献。

  • 同理,ApplicationThread同上述一樣做了更改:
 private class ApplicationThread extends IApplicationThread.Stub {
    ...
 }

所以在Android 8.0上不存在ActivityManagerProxy和ApplicationThreadProxy埂淮,而是采用了AIDL接口的方式來進(jìn)行通信的姑隅。

源碼調(diào)用棧(基于Android 8.0)

按照自上而下的調(diào)用棧的順序進(jìn)行調(diào)用,以類文件為單位來計(jì)步同诫,方便大家去了解調(diào)用流程粤策,主要涉及的幾個(gè)源文件:Instumentation,ActivityMangerService,ActivityStack,ActivityStarter,ActivityStackSupervisor,ActivityThread,Activity等。

  1. Activity
public void startActivity(Intent intent)
    
public void startActivity(Intent intent, @Nullable Bundle options)

public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options)
  1. Intrumentation
public ActivityResult execStartActivity(
    Context who, IBinder contextThread, IBinder token, Activity target,
    Intent intent, int requestCode, Bundle options){
    ...
    int result = ActivityManager.getService()
        .startActivity(whoThread, who.getBasePackageName(), intent,
            intent.resolveTypeIfNeeded(who.getContentResolver()),
            token, target != null ? target.mEmbeddedID : null,
            requestCode, 0, null, options);
    ...
}
  1. ActivityManagerService
public final int startActivity(IApplicationThread caller, String callingPackage,
    Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
    int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
    ...
    return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, bOptions,
                UserHandle.getCallingUserId());
}
     
            
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
    Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId) {
    ...
    return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, bOptions, false, userId, null, "startActivityAsUser");
}
  1. ActivityStarter
final int startActivityMayWait(IApplicationThread caller, int callingUid,
    String callingPackage, Intent intent, String resolvedType,
    IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
    IBinder resultTo, String resultWho, int requestCode, int startFlags,
    ProfilerInfo profilerInfo, WaitResult outResult,
    Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, 
    int userId,askRecord inTask, String reason) { 
    ...
    int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
        aInfo, rInfo, voiceSession, voiceInteractor,
        resultTo, resultWho, requestCode, callingPid,
        callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
        options, ignoreTargetSecurity, componentSpecified, outRecord, inTask,
        reason);
    ...
}
        

int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
    String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
    IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
    IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
    String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
    ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
    ActivityRecord[] outActivity, TaskRecord inTask, String reason) {
    ...
    mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
    aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
    callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
    options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
            inTask);
    ...
}
            
private int startActivity(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
    String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
    IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
    IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
    String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
    ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
    ActivityRecord[] outActivity, TaskRecord inTask) {
    ...
    doPendingActivityLaunchesLocked(false);
    return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
    options, inTask, outActivity);
}
            

private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
    IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
    int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
    ActivityRecord[] outActivity) {
    ...
    result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
        startFlags, doResume, options, inTask, outActivity);
    ...
}  
            
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
    IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
    int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
    ActivityRecord[] outActivity) {
    ...
    if (mDoResume) {
        mSupervisor.resumeFocusedStackTopActivityLocked();
    }
    ...
}
  1. ActivityStackSupervisor
boolean resumeFocusedStackTopActivityLocked() {
    return resumeFocusedStackTopActivityLocked(null, null, null);
}
    
boolean resumeFocusedStackTopActivityLocked(
    ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
    ...
    if (r == null || r.state != RESUMED) {
        mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
    } 
    ...
}
  1. ActivityStack
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
    ...
    result = resumeTopActivityInnerLocked(prev, options);
    ...
}

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) { 
   ....
    if (mResumedActivity != null) {
        //同步等待pause當(dāng)前Activity的結(jié)果
        pausing |= startPausingLocked(userLeaving, false, next, false);
    }
    ....
      //開始啟動(dòng)下一個(gè)Activity
      mStackSupervisor.startSpecificActivityLocked(next, true, false);
    ....
}


final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, ActivityRecord resuming, boolean pauseImmediately) {
    ....
    //去當(dāng)前Activity所在應(yīng)用進(jìn)程暫停當(dāng)前activity
     prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
            userLeaving, prev.configChangeFlags, pauseImmediately);
    ....
}
       
  1. ActivityThread$ApplicationThread
public final void schedulePauseActivity(IBinder token, boolean finished, boolean userLeaving, int configChanges, boolean dontReport) {
    ...
    sendMessage(finished ? H.PAUSE_ACTIVITY_FINISHING: H.PAUSE_ACTIVITY, token,
    (userLeaving ? USER_LEAVING: 0) | (dontReport ? DONT_REPORT: 0), configChanges, seq);
    ...
}
  1. ActivityThread
private void sendMessage(int what, Object obj, int arg1, int arg2, int seq) {
    Message msg = Message.obtain();
    ....
    mH.sendMessage(msg);
}
  1. ActivityThread$H
public void handleMessage(Message msg) {
   ...
    switch (msg.what) {
    case PAUSE_ACTIVITY:
        {
            SomeArgs args = (SomeArgs) msg.obj;
            handlePauseActivity((IBinder) args.arg1, false, (args.argi1 & USER_LEAVING) != 0,
            args.argi2, (args.argi1 & DONT_REPORT) != 0, args.argi3);
        }
        break;
    }
    ...
}
  1. ActivityThread
private void handlePauseActivity(IBinder token, boolean finished, 
    boolean userLeaving, int configChanges, boolean dontReport, int seq) {
    ...
    performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");
    ...
    //執(zhí)行完后通知AMS當(dāng)前Activity已經(jīng)pause
    ActivityManager.getService().activityPaused(token);
    ...
}

final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
     boolean saveState, String reason) {
         ...
         performPauseActivityIfNeeded(r, reason);
         ...
}


private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
    ...
     mInstrumentation.callActivityOnPause(r.activity);
    ...
}
  1. Instrumentation
public void callActivityOnPause(Activity activity) {
    activity.performPause();
}
  1. Activity
final void performPause() {
    ...
    onPause();
    ...
}

由于在ActivityThread中handlePauseActivity的方法里误窖,在pause成功后,需要通知AMS已經(jīng)pause成功秩贰,所以接著分析ActivityManagerService.activityPaused方法霹俺。

  1. ActivityManagerService
public final void activityPaused(IBinder token) {
    final long origId = Binder.clearCallingIdentity();
    synchronized(this) {
        ActivityStack stack = ActivityRecord.getStackLocked(token);
        if (stack != null) {
            stack.activityPausedLocked(token, false);
        }
    }
    Binder.restoreCallingIdentity(origId);
}
  1. ActivityStack
final void activityPausedLocked(IBinder token, boolean timeout) {
    ...
    mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
    ...
    completePauseLocked(true /* resumeNext */, null /* resumingActivity */);
    ...
}

private void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
    ...
    mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null);
    ...
}
  1. ActivityStackSupervisor
boolean resumeFocusedStackTopActivityLocked(ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
    //如果啟動(dòng)Activity和要啟動(dòng)的Activity在同一個(gè)ActivityStack中,調(diào)用targetStack對(duì)象的方法
    if (targetStack != null && isFocusedStack(targetStack)) {
        return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
    }
    //如果不在同一個(gè)ActivityStack中毒费,則調(diào)用mFocusStack對(duì)象的方法
    if (r == null || r.state != RESUMED) {
        mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
    }

    return false;
}
  1. ActivityStatck
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
    ...
    result = resumeTopActivityInnerLocked(prev, options);
    ...
}

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) { 
   ...
    if (mResumedActivity != null) {
        //同步等待pause當(dāng)前Activity的結(jié)果,但在pause時(shí)丙唧,已經(jīng)把mResumedActivity置為了null,所以不走這里
        pausing |= startPausingLocked(userLeaving, false, next, false);
        ...
    }
    ...
    return true;
    ...
      //開始啟動(dòng)下一個(gè)Activity
      mStackSupervisor.startSpecificActivityLocked(next, true, false);
    ...
}
  1. ActivityStackSupervisor
void startSpecificActivityLocked(ActivityRecord r,
    boolean andResume, boolean checkConfig) { 
    if (app != null && app.thread != null) { 
        ...
        realStartActivityLocked(r, app, andResume, checkConfig);
        return;
    }
    ...
    //啟動(dòng)跨進(jìn)程的Activity需要先開啟新的應(yīng)用進(jìn)程
    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
        "activity", r.intent.getComponent(), false, false, true);
}

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
    boolean andResume, boolean checkConfig) throws RemoteException { 
    ...
    app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
        System.identityHashCode(r), r.info,
        // TODO: Have this take the merged configuration instead of separate global
        // and override configs.
        mergedConfiguration.getGlobalConfiguration(),
        mergedConfiguration.getOverrideConfiguration(), r.compat,
        r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
        r.persistentState, results, newIntents, !andResume,
        mService.isNextTransitionForward(), profilerInfo);
    ...
}
  1. ActivityThread$ApplicationThread
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
    ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
    CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
    int procState, Bundle state, PersistableBundle persistentState,
    List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
    boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
    ...
    sendMessage(H.LAUNCH_ACTIVITY, r);
}
  1. ActivityThread
private void sendMessage(int what, Object obj) {
    sendMessage(what, obj, 0, 0, false);
}
 
 
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
    ...
    mH.sendMessage(msg);
} 
 
  1. ActivityThread$H
public void handleMessage(Message msg) {
    ...
    switch (msg.what) {
    case LAUNCH_ACTIVITY:
        {
            ....
            handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
            ....
        }
        break;
        ...
    }
}
  1. ActivityThread
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
    ...
    Activity a = performLaunchActivity(r, customIntent);
}

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent){ 
    ...
    if (r.isPersistable()) {
        mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
    } else {
        mInstrumentation.callActivityOnCreate(activity, r.state);
    }
    ...
}
  1. Instumentation
public void callActivityOnCreate(Activity activity, Bundle icicle) {
    prePerformCreate(activity);
    activity.performCreate(icicle);
    postPerformCreate(activity);
}
  1. Activity
final void performCreate(Bundle icicle) {
    performCreate(icicle, null);
}

final void performCreate(Bundle icicle, PersistableBundle persistentState) {
    ...
    if (persistentState != null) {
        onCreate(icicle, persistentState);
    } else {
        onCreate(icicle);
    }
   ...
}

Activity啟動(dòng)流程

為了敘述方便觅玻,我們假設(shè)Activity A要啟動(dòng)Activity B想际。

  1. Activity A向AMS發(fā)送一個(gè)啟動(dòng)Activity B的進(jìn)程間通信請(qǐng)求;
  2. AMS會(huì)將要啟動(dòng)的Activity B的組件信息保存下來溪厘,然后通過Binder通信(ApplicationThread及其接口定義語言)胡本,讓Activity A執(zhí)行pause操作;
  3. Activity B完成pause操作后畸悬,通過Binder通信(ActivityManagerService及其接口定義語言)通知AMS侧甫,可以執(zhí)行啟動(dòng)Activity B的操作了(要啟動(dòng)的activity信息保存在了棧頂);
  4. 在啟動(dòng)之前,如果發(fā)現(xiàn)Activity B的應(yīng)用程序進(jìn)程不存在披粟,會(huì)先啟動(dòng)一個(gè)新的進(jìn)程(上述調(diào)用棧沒涉及咒锻,同學(xué)們可自行查看源碼);
  5. AMS執(zhí)行一系列啟動(dòng)Activity B的操作守屉,并通過Binder通信(ApplicationThread及其接口定義語言)進(jìn)行跨進(jìn)程調(diào)用惑艇,將Activity B啟動(dòng)起來;

關(guān)于AMS

  • AMS的啟動(dòng)是在SystemServer(系統(tǒng)進(jìn)程)中啟動(dòng)的拇泛,同其他Android應(yīng)用一樣敦捧,也是由Zygote進(jìn)程fork出來的:
public final class SystemServer {

    /**
     * The main entry point from zygote.
     * 注釋寫的很清楚了,SystemServer進(jìn)程是有Zygote進(jìn)程fork出來的
     */
    public static void main(String[] args) {
        new SystemServer().run();
    }    
    
    private void run() {
        ...
         startBootstrapServices();
        ...
    }
    
    private void startBootstrapServices() {
        ...
        // Activity manager runs the show.
        traceBeginAndSlog("StartActivityManager");
        //開啟ActivityManagerService進(jìn)程
        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);
        traceEnd();        
        ...
    }    
}
  • AMS與APP進(jìn)程的通信:
  1. APP進(jìn)程通過IActivityManager.aidl接口向AMS進(jìn)程進(jìn)行通信碰镜。
    ActivityManager.getService()獲得AMS的Binder接口兢卵,再通過Stub.asInterface的方式,轉(zhuǎn)成IActivityManager的接口绪颖,通過IActivityManager與AMS進(jìn)行通信秽荤,實(shí)現(xiàn)RPC遠(yuǎn)程跨進(jìn)程調(diào)用;
    Instrumentation
int result = ActivityManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target, requestCode, 0, null, options);

ActivityManager

public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
}
 
private static final Singleton<IActivityManager> IActivityManagerSingleton =
    new Singleton<IActivityManager>() {
        @Override
        protected IActivityManager create() {
            final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
            final IActivityManager am = IActivityManager.Stub.asInterface(b);
            return am;
        }
};

  1. AMS進(jìn)程通過IApplication.aidl接口向APP進(jìn)程進(jìn)行通信柠横。
    在AMS內(nèi)部持有每個(gè)ActivityThread的IApplicatinThread接口實(shí)例窃款,用時(shí)可以直接調(diào)用。同IActivityManager,也是通過Binder進(jìn)行進(jìn)程間通信牍氛。

參考鏈接
【凱子哥帶你學(xué)Framework】Activity啟動(dòng)過程全解析
Activity啟動(dòng)流程簡直喪心病狂晨继!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市搬俊,隨后出現(xiàn)的幾起案子紊扬,更是在濱河造成了極大的恐慌,老刑警劉巖唉擂,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件餐屎,死亡現(xiàn)場離奇詭異,居然都是意外死亡玩祟,警方通過查閱死者的電腦和手機(jī)腹缩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來空扎,“玉大人藏鹊,你說我怎么就攤上這事∽猓” “怎么了盘寡?”我有些...
    開封第一講書人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長黑忱。 經(jīng)常有香客問我宴抚,道長勒魔,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任菇曲,我火速辦了婚禮冠绢,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘常潮。我一直安慰自己弟胀,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開白布喊式。 她就那樣靜靜地躺著孵户,像睡著了一般。 火紅的嫁衣襯著肌膚如雪岔留。 梳的紋絲不亂的頭發(fā)上夏哭,一...
    開封第一講書人閱讀 51,365評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音献联,去河邊找鬼竖配。 笑死,一個(gè)胖子當(dāng)著我的面吹牛里逆,可吹牛的內(nèi)容都是我干的进胯。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼原押,長吁一口氣:“原來是場噩夢啊……” “哼胁镐!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起诸衔,我...
    開封第一講書人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤盯漂,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后署隘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宠能,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年磁餐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片阿弃。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡诊霹,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出渣淳,到底是詐尸還是另有隱情脾还,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布入愧,位于F島的核電站鄙漏,受9級(jí)特大地震影響嗤谚,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜怔蚌,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一巩步、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧桦踊,春花似錦椅野、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至杖狼,卻和暖如春炼蛤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蝶涩。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來泰國打工理朋, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人子寓。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓暗挑,卻偏偏與公主長得像,于是被迫代替她去往敵國和親斜友。 傳聞我的和親對(duì)象是個(gè)殘疾皇子炸裆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容