AMS与Activity的交互

来源:互联网 发布:org.apache.tiles 编辑:程序博客网 时间:2024/05/16 07:14

这里写图片描述
上面是Activity典型的生命周期流程图,基本的就不讲了,提两个问题来求解下
1:当启动一个新的Activity时,新旧两个Activity的生命周期执行顺序
2:当你在onCreat中调用startActivity或者finish的时候,生命周期执行流程

首先来求解第一个问题,很简单,建立两个Activity,每个生命周期上打上log

@Overrideprotected void onStart() {   Log.e("xw", "111---onStart");   super.onStart();}@Overrideprotected void onStart() {   Log.e("xw", "222---onStart");   super.onStart();}

跳转之后log为
这里写图片描述
可以看到首先调用了第一个Activity的onPause方法,之后第二个Activity的onCreat,onStart,onResume方法依次执行,最后才轮到第一个Activity的onStop方法。
先不从实现单从产品的角度来讲,这种执行顺序很有道理,因为onPause执行后意味着Activity不再接收事件,所以onPause必定要在第二个Activity的onResume方法之前执行,否则会导致有两个Activity可以接收事件,这显然不合理。而各种系统都要考虑的就是响应速度,从安卓来讲,就是要最快的展示给用户新的Activity,也就是新的Activity的生命周期要尽早执行,所以,最终结论是,首先终止第一个Activity接收事件的能力,之后展现新的Activity,最后第一个Activity再去进行收尾工作。具体的实现等下再说。
接着是第二个问题,首先看调用startActivity

@Override    protected void onCreate(Bundle savedInstanceState) {        Log.e("xw", "111---onCreate");        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        startActivity(new Intent(MainActivity.this, Main2Activity.class));    }

打印的log为
这里写图片描述
可以看到完整的执行了整个生命周期,而且第一个onPause首先执行,接着是finish

@Override    protected void onCreate(Bundle savedInstanceState) {        Log.e("xw", "111---onCreate");        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        finish();    }

这里写图片描述
可以看到只执行了onCreate和与之对应的onDestroy,那么我们把finish放在onStart中,看看会发生什么

@Override    protected void onStart() {        Log.e("xw", "111---onStart");        finish();        super.onStart();    }

这里写图片描述
可以看到,同样如此,没有完整的执行整个生命周期
下面我们开始分析原因
首先我们要知道Activity的生命周期调用是由Framework中的AMS决定的,我们看看到底请求如何从应用传递到AMS
startActivity最终都会调用到startActivityForResult这个方法中,我们看看他做了什么

@Override    public void startActivityForResult(            String who, Intent intent, int requestCode, @Nullable Bundle options) {        Uri referrer = onProvideReferrer();        if (referrer != null) {            intent.putExtra(Intent.EXTRA_REFERRER, referrer);        }        Instrumentation.ActivityResult ar =            mInstrumentation.execStartActivity(                this, mMainThread.getApplicationThread(), mToken, who,                intent, requestCode, options);        if (ar != null) {            mMainThread.sendActivityResult(                mToken, who, requestCode,                ar.getResultCode(), ar.getResultData());        }        cancelInputsAndStartExitTransition(options);    }

关键在于mInstrumentation的execStartActivity方法

public ActivityResult execStartActivity(        Context who, IBinder contextThread, IBinder token, String target,        Intent intent, int requestCode, Bundle options) {        ......        try {            intent.migrateExtraStreamToClipData();            intent.prepareToLeaveProcess(who);            int result = ActivityManagerNative.getDefault()                .startActivity(whoThread, who.getBasePackageName(), intent,                        intent.resolveTypeIfNeeded(who.getContentResolver()),                        token, target, requestCode, 0, null, options);            checkStartActivityResult(result, intent);        } catch (RemoteException e) {            throw new RuntimeException("Failure from system", e);        }        return null;    }

其中ActivityManagerNative.getDefault()获取的就是AMS的代理类,我们可以利用它远程调用AMS的各种方法,在这里,我们将调用AMS的startActivity,这样请求就从应用传递给了AMS
接着看看finish方法

public void finish() {        finish(DONT_FINISH_TASK_WITH_ACTIVITY);    }private void finish(int finishTask) {        if (mParent == null) {            int resultCode;            Intent resultData;            synchronized (this) {                resultCode = mResultCode;                resultData = mResultData;            }            if (false) Log.v(TAG, "Finishing self: token=" + mToken);            try {                if (resultData != null) {                    resultData.prepareToLeaveProcess(this);                }                if (ActivityManagerNative.getDefault()                        .finishActivity(mToken, resultCode, resultData, finishTask)) {                    mFinished = true;                }            } catch (RemoteException e) {                // Empty            }        } else {            mParent.finishFromChild(this);        }    }

也是利用ActivityManagerNative.getDefault()将请求传递给了AMS

AMS收到消息后根据请求内部进行一系列操作,之后也是通过IPC调用,将需要的操作通知应用进程。

应用进程其实就是一个ActivityThread,而负责接收AMS消息的则是ActivityThread的一个内部类ApplicationThread,他也是一个binder,它里面的方法中很明显的有几个涉及基本的生命周期调用

scheduleLaunchActivity
scheduleResumeActivity
schedulePauseActivity
scheduleStopActivity
scheduleDestroyActivity

其中scheduleLaunchActivity适用于新建一个Activity,scheduleResumeActivity适用将已有的Activity重新展示,schedulePauseActivity由于之前所说的原因所以会单独调用,scheduleStopActivity适用于startActivity时旧的Activity,而scheduleDestroyActivity适用于finish是旧的Activity,可以看到也是除了schedulePauseActivity较为特殊,也是一一对应的关系。

下面我们看看scheduleLaunchActivity的具体实现

@Override        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);        }

因为binder的代码会运行在他开启的线程中,所以要使用Handler将消息发送到主线程中,利用ActivityThread中H这个Handler来进行处理,看看H的处理方式

case LAUNCH_ACTIVITY: {     ......     handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");    } break;

调用到handleLaunchActivity方法中

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {    ......    Activity a = performLaunchActivity(r, customIntent);    ......    handleResumeActivity(r.token, false, r.isForward,!r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);    ......    }

关键的就是这两个,先看第一句performLaunchActivity

 private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {        ......        Activity activity = null;        try {            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();            activity = mInstrumentation.newActivity(                    cl, component.getClassName(), r.intent);            ......        } ......         activity.attach(appContext, this, getInstrumentation(), r.token,                        r.ident, app, r.intent, r.activityInfo, title, r.parent,                        r.embeddedID, r.lastNonConfigurationInstances, config,                        r.referrer, r.voiceInteractor, window);                ......                if (r.isPersistable()) {                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);                } else {                    mInstrumentation.callActivityOnCreate(activity, r.state);                }               ......                r.activity = activity;                r.stopped = true;                if (!r.activity.mFinished) {                    activity.performStart();                    r.stopped = false;                }                ......        return activity;    }

重要的以下四点:
1:根据传递进的参数利用ClassLoader构建Activity类
2:调用Activity的attach的方法,里面将Activity的各种参数初始化,并且设置了Activity关联的PhoneWindow类,很重要,但是和现在讲的生命周期关系不大
3:mInstrumentation.callActivityOnCreate方法,在里面Activity调用了我们熟悉的onCreat方法
4:activity.performStart()里面调用了Activity的onStart方法,当然要调用的首先会判断mFinished的值,我们再看下前面的finish方法,里面在将消息发送给AMS后还将mFinished置为TRUE,这解释了为什么在onCreat调用finish后onStart方法不会被调用到。在调用完onStart之后还会将stopped置为false,这个将之后用于判断是否去执行onStop方法
看完performLaunchActivity,我们接着去看看handleResumeActivity方法,从名字就可以看出是用来调用onResume方法的

final void handleResumeActivity(IBinder token,            boolean clearHide, boolean isForward, boolean reallyResume, int seq, String reason) {        ......        r = performResumeActivity(token, clearHide, reason);        ......        ActivityManagerNative.getDefault().activityResumed(token);    }public final ActivityClientRecord performResumeActivity(IBinder token,            boolean clearHide, String reason) {        ......        if (r != null && !r.activity.mFinished) {            ......            r.activity.performResume();            r.paused = false;            r.stopped = false;            ......        }        return r;    }

也会判断mFinished的值,之后调用onResume。
如果正常情况下的话,scheduleLaunchActivity会使一个新的Activity对象被创建,并且成功调用onCreate,onStart,onResume方法,并将paused 和stopped 值置为false,最后将成功启动Activity的消息通知AMS

所以同理scheduleResumeActivity会去执行Activity的onStart和onResume方法,scheduleStopActivity和scheduleDestroyActivity也同样,拿schedulePauseActivity做个代表再说下,schedulePauseActivity发消息后会执行ActivityThread的handlePauseActivity方法

private void handlePauseActivity(IBinder token, boolean finished,            boolean userLeaving, int configChanges, boolean dontReport, int seq) {        ActivityClientRecord r = mActivities.get(token);        if (r != null) {            ......            performPauseActivity(token, finished, r.isPreHoneycomb(), "handlePauseActivity");            ......            ActivityManagerNative.getDefault().activityPaused(token);                  }    }

同样,调用performPauseActivity然后去通知AMS,看看performPauseActivity方法

final Bundle performPauseActivity(IBinder token, boolean finished,            boolean saveState, String reason) {        ActivityClientRecord r = mActivities.get(token);        return r != null ? performPauseActivity(r, finished, saveState, reason) : null;    }final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,            boolean saveState, String reason) {        if (r.paused) {            if (r.activity.mFinished) {                // If we are finishing, we won't call onResume() in certain cases.                // So here we likewise don't want to call onPause() if the activity                // isn't resumed.                return null;            }        .....        }        .....        performPauseActivityIfNeeded(r, reason);        ......    }

首先就告诉我们如果调用了finish但是没有调过onResume那么就什么都不做,直接返回,否则的话就会去调用performPauseActivityIfNeeded,里面会调用Activity的onPause方法。

原创粉丝点击