源码探探之StartActivity(一)

源码基于API 26

startActivity()上车

@Override
public void startActivity(Intent intent) {
    this.startActivity(intent, null);
}

没什么好说的

//启动一个activity不需要返回值
//如果context之外调用startActivity(),需要给intent添加{@link Intent#FLAG_ACTIVITY_NEW_TASK}
//@param options 附加的选项指示如果启动activity
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
    if (options != null) {
        startActivityForResult(intent, -1, options);
    } else {
        //可重写该方法兼容应用需求
        startActivityForResult(intent, -1);
    }
}

可重写该方法,参考FragmentActivity

//If requestCode >= 0, this code will be returned in onActivityResult() when the activity exits.
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {
    startActivityForResult(intent, requestCode, null);
}

最终执行该方法

//启动一个activity在finish()会返回一个结果在onActivityResult()中
//如果在onCreate()/onResume()方法中调用该方法,window不显示界面直到该方法返回结果
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
        @Nullable Bundle options) {
    //父activity一般为空
    if (mParent == null) {
        //通过ActivityOptions帮助类生成一个bundle,指示该如何启动该activity
        options = transferSpringboardActivityOptions(options);
        //Instrumentation基类启动Activity
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
                this, mMainThread.getApplicationThread(), mToken, this,
                intent, requestCode, options);
        //返回结果
        if (ar != null) {
            //最终会执行Activity的onActivityResult()
            mMainThread.sendActivityResult(
                mToken, mEmbeddedID, requestCode, ar.getResultCode(),
                ar.getResultData());
        }
        if (requestCode >= 0) {
            //当接收到返回的结果了启动的activity才会显示
            mStartedActivity = true;
        }
        //取消输入并开始activity退出动画
        cancelInputsAndStartExitTransition(options);
    } else {
        //不考虑mParent不为null的情况,远古级方法,不采用了
        if (options != null) {
            mParent.startActivityFromChild(this, intent, requestCode, options);
        } else {
            mParent.startActivityFromChild(this, intent, requestCode);
        }
    }
}

执行Instrumentation的execStartActivity(),Instrumentation起着监控系统和应用的作用

//target:源activity
public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    //获取当前内容索引,不重写onProvideReferrer()返回null
    Uri referrer = target != null ? target.onProvideReferrer() : null;
    if (referrer != null) {
        //不为null添加至intent
        intent.putExtra(Intent.EXTRA_REFERRER, referrer);
    }
    //activity监视器
    if (mActivityMonitors != null) {
        synchronized (mSync) {
            final int N = mActivityMonitors.size();
            for (int i=0; i<N; i++) {
                final ActivityMonitor am = mActivityMonitors.get(i);                    
                if (am.match(who, null, intent)) {
                    am.mHits++;
                    if (am.isBlocking()) {
                        return requestCode >= 0 ? am.getResult() : null;
                    }
                    break;
                }
            }
        }
    }
    try {
        //内容是否有迁移
        intent.migrateExtraStreamToClipData();
        //准备intent并离开当前进程
        intent.prepareToLeaveProcess(who);
        //本地activityManager启动activity
        int result = ActivityManagerNative.getDefault()
            .startActivity(whoThread, who.getBasePackageName(), intent,
                    intent.resolveTypeIfNeeded(who.getContentResolver()),
                    token, target != null ? target.mEmbeddedID : null,
                    requestCode, 0, null, options);
        //检查启动activity返回结果,抛出异常
        checkStartActivityResult(result, intent);
        //跨进程异常
    } catch (RemoteException e) {
        throw new RuntimeException("Failure from system", e);
    }
    return null;
}

ActivityManagerNative.getDefault()获取IActivityManager接口,调用startActivity()方法。
事实上是ServiceManager.getService("activity"), 即获取ActivityManagerService(AMS)并通过Binder远程调用ActivityManagerService类的startActivity()方法。

private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
    protected IActivityManager create() {
        //获取activityService
        IBinder b = ServiceManager.getService("activity");
        if (false) {
            Log.v("ActivityManager", "default service binder = " + b);
        }
        //返回service代理对象
        IActivityManager am = asInterface(b);
        if (false) {
            Log.v("ActivityManager", "default service = " + am);
        }
        return am;
    }
};
static public IActivityManager asInterface(IBinder obj) {
    if (obj == null) {
        return null;
    }
    //通过binder获取AMS
    IActivityManager in =
        (IActivityManager)obj.queryLocalInterface(descriptor);
    if (in != null) {
        return in;
    }
    //代理obj其实就是AMS
    return new ActivityManagerProxy(obj);
}

IAvityManager对所有运行着的Activity交互提供了接口,ActivityMangerNative实现了IActivityManager接口,IActivityManger的大多数功能都是调用了ActivityManagerNative类接口来完成的,而AMS继承了ActivityMangerNative。
ActivityMangerNative作为IActivityManger和AMS的中间类,解耦了两者间的依赖,所有对AMS的访问都转换成了对ActivityMangerNative的代理类ActivityMangerProxy的访问。

从这里的getDefault().startActivity()开始从本应用通过binder跨进程调用AMS的方法

@Override
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());
}
@Override
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) {
    enforceNotIsolatedCaller("startActivity");
    userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
            userId, false, ALLOW_FULL_ONLY, "startActivity", null);
    // TODO: Switch to user app stacks here.
    return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
            resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
            profilerInfo, null, null, bOptions, false, userId, null, null);
}

ActivityStarter类负责处理启动activity之前的准备工作,包括Activity的Intent和Flags的逻辑, 还有管理Stack和TaskRecord.
ActivityStarter类的调用流程:

  • ActivityStarter#startActivityMayWait(根据Intent获取Activity的启动信息(ResolveInfo和ActivityInfo)
  • ActivityStarter#startActivityLocked(创建ActivityRecord, 含有Activity的核心信息)
  • ActivityStarter#startActivityUnchecked(根据启动的Flag信息, 设置TaskRecord)

接着执行ActivityStackSupervisor类的resumeFocusedStackTopActivityLocked()方法

boolean resumeFocusedStackTopActivityLocked(
        ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
    if (targetStack != null && isFocusedStack(targetStack)) {
        return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
    }
    final ActivityRecord r = mFocusedStack.topRunningActivityLocked();
    if (r == null || r.state != RESUMED) {
        mFocusedStack.resumeTopActivityUncheckedLocked(null, null);
    }
    return false;
}

ActivityStackSupervisor类与ActivityStack类配合使用. ActivityStackSupervisor负责管理Task和Stack, 而ActivityStack负责管理在Stack和Task中的Activity

ActivityStackSupervisor类与ActivityStack类的调用流程:

  • ActivityStackSupervisor#resumeFocusedStackTopActivityLocked

  • ActivityStack#resumeTopActivityUncheckedLocked

  • ActivityStack#resumeTopActivityInnerLocked(根据ActivityRecord和ActivityOptions完成Activity的切换, 移至栈顶)

  • ActivityStackSupervisor#startSpecificActivityLocked

  • ActivityStackSupervisor#realStartActivityLocked(真正启动activity)

     final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
             boolean andResume, boolean checkConfig) throws RemoteException {
         ...
         app.forceProcessStateUpTo(mService.mTopProcessState);
         app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                 System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
                 new Configuration(task.mOverrideConfig), r.compat, r.launchedFromPackage,
                 task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
                 newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
         ...
     }
    

最后由ActivityThread中的ApplicationThread调用scheduleLaunchActivity完成Activity的真正启动。
这里的thread是IApplicationThread接口,该接口继承了IInterface接口,实现方法asBinder()方法作为binder通信。

这里通过binder跨进程由系统进程调用应用进程启动activity

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,657评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,889评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,057评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,509评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,562评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,443评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,251评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,129评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,561评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,779评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,902评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,621评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,220评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,838评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,971评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,025评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,843评论 2 354

推荐阅读更多精彩内容