AndroidソースからActivityロードプロセスを分析する
16286 ワード
概要:startActivity->startActivity ForResult->Instrumentation::execStartActivity->scheduleLaunchActivity->performLaunchActivity->handleLaunchActivity->handleLaunchActivity->handleResumeActivity
AndroidソースでActivityのロード手順を説明します.まずはActivity.JAvaのstartActivityの開始:
startActivityもstartActivity ForResultを呼び出すことによって実現されていることがわかり、次にstartActivity ForResultの実現について検討する.
Activity.java
ここではInstrumentationクラスのexecStartActivityメソッドでActivityを起動します.
Instrumentation.java
whoThreadは、IApplicationThreadインタフェースを実装するクラスのインスタンスであり、IApplicationThreadインタフェースは、システムがアプリケーションと対話するAPIを提供し、アプリケーションが起動すると、アプリケーションがIApplicationThreadインタフェースを実装するインスタンスがActivity Managerに転送され、Activity Managerは、このインスタンスを介してアプリケーションの起動、一時停止、Activityの停止などの一連の操作を指導する.
ここでActivityを起動する関数はscheduleLaunchActivityであり、この関数の実現はActivity ThreadクラスのプライベートクラスApplicationThreadにある:Activity Thread.java
ここで、ApplicationThreadNativeはIApplicationThreadインタフェースを実現した.
ApplicationThreadでは、Activityへのアクセス、Activityを識別するtoken、AndroidManifestの格納など、多くの関数パラメータを持つscheduleLaunchActivityの実装を見る.xml中和タグセグメント情報のactivityInfoは、システムレベルとユーザレベルの構成curConfig(画面方向、現在の国とフォントのスケーリング設定など)を格納.getConfiguration()など.これらのパラメータをActivity ClientRecordに割り当て、sendMessageを使用してLAUNCH_のタイプを送信します.ACTIVITYのメッセージ.sendMessageの実装を見てみましょう.
ActivityThread.java
sendMessageとは,Messageを構築し,HタイプのHandlerを介して送信することである.Hの定義を見てみましょう.
ActivityThread.java
HタイプのHandlerでは様々なタイプのメッセージが処理され、関数handleLaunchActivityでLAUNCH_が処理されるACTIVITYメッセージ:
ActivityThread.java
ここには主に3つの操作が含まれており、performLaunchActivityはActivityを起動し、handleResumeActivityはResume Activityに来て、最後にInstrumentationのcallActivity OnPause関数を通じてOnPause Activityになります.performLaunchActivityの実装を見てみましょう.
ActivityThread.java
まずjavaを通ります.lang.ClassLoaderは、InstrumentationのnewActivityメソッドを呼び出し、Activityの名前に従ってActivityクラスをロードします.
Instrumentation.java
次に、ActivityのcontextをcreateBaseContextForActivityで生成し、activityを介して生成する.attachメソッドは、Activityのcontextおよびその他の属性をActivityに割り当てます.次にInstrumentationのcallActivity OnCreateメソッド、callActivity OnRestoreInstanceStateメソッド、callActivity OnPostCreateメソッドを呼び出し、それぞれActivityのonCreateメソッド、onRestoreInstanceStateメソッド、onPostCreateメソッドに対応します.これにより、performLaunchActivity関数でActivityのロードと初期化プロセスが完了します.
handleLaunchActivity関数に戻り、performLaunchActivityが完了した後、handleResumeActivityメソッドによりActivityがonResumeの準備を完了し、onResume状態に入る.最後に、InstrumentationのcallActivity OnPauseメソッドを呼び出し、ActivityをonPauseの状態にします.これにより、Activityが最終的に表示されると、onResumeから開始します.これでActivityのロードが完了しました.
AndroidソースでActivityのロード手順を説明します.まずはActivity.JAvaのstartActivityの開始:
@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
startActivityForResult(intent, -1);
}
}
startActivityもstartActivity ForResultを呼び出すことによって実現されていることがわかり、次にstartActivity ForResultの実現について検討する.
Activity.java
@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);
}
ここではInstrumentationクラスのexecStartActivityメソッドでActivityを起動します.
Instrumentation.java
public ActivityResult execStartActivity(
Context who,
IBinder contextThread,
IBinder token,
Activity target,
Intent intent,
int requestCode,
Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
Uri referrer = target != null ? target.onProvideReferrer() : null;
if (referrer != null) {
intent.putExtra(Intent.EXTRA_REFERRER, referrer);
}
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, options);
checkStartActivityResult(result, intent);
} catch (RemoteException e) {
throw new RuntimeException("Failure from system", e);
}
return null;
}
whoThreadは、IApplicationThreadインタフェースを実装するクラスのインスタンスであり、IApplicationThreadインタフェースは、システムがアプリケーションと対話するAPIを提供し、アプリケーションが起動すると、アプリケーションがIApplicationThreadインタフェースを実装するインスタンスがActivity Managerに転送され、Activity Managerは、このインスタンスを介してアプリケーションの起動、一時停止、Activityの停止などの一連の操作を指導する.
public interface IApplicationThread extends IInterface {
void schedulePauseActivity(IBinder token, boolean finished, boolean userLeaving,
int configChanges, boolean dontReport) throws RemoteException;
void scheduleStopActivity(IBinder token, boolean showWindow, int configChanges) throws RemoteException;
void scheduleWindowVisibility(IBinder token, boolean showWindow) throws RemoteException;
void scheduleSleeping(IBinder token, boolean sleeping) throws RemoteException;
void scheduleResumeActivity(IBinder token, int procState, boolean isForward, Bundle resumeArgs) throws RemoteException;
void scheduleSendResult(IBinder token, List results) throws RemoteException;
void scheduleLaunchActivity(.....);
void scheduleRelaunchActivity(......);
void scheduleDestroyActivity(......);
...
}
ここでActivityを起動する関数はscheduleLaunchActivityであり、この関数の実現はActivity ThreadクラスのプライベートクラスApplicationThreadにある:Activity Thread.java
public final class ActivityThread {
...
private class ApplicationThread extends ApplicationThreadNative {
@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 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.referrer = referrer;
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;
r.overrideConfig = overrideConfig;
updatePendingConfiguration(curConfig);
sendMessage(H.LAUNCH_ACTIVITY, r);
}
...
}
ここで、ApplicationThreadNativeはIApplicationThreadインタフェースを実現した.
public abstract class ApplicationThreadNative extends Binder
implements IApplicationThread {
...
}
ApplicationThreadでは、Activityへのアクセス、Activityを識別するtoken、AndroidManifestの格納など、多くの関数パラメータを持つscheduleLaunchActivityの実装を見る.xml中和タグセグメント情報のactivityInfoは、システムレベルとユーザレベルの構成curConfig(画面方向、現在の国とフォントのスケーリング設定など)を格納.getConfiguration()など.これらのパラメータをActivity ClientRecordに割り当て、sendMessageを使用してLAUNCH_のタイプを送信します.ACTIVITYのメッセージ.sendMessageの実装を見てみましょう.
ActivityThread.java
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
if (DEBUG_MESSAGES)
Slog.v(TAG, "SCHEDULE " + what + " " + mH.codeToString(what) + ": " + arg1 + " / " + obj);
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
if (async) {
msg.setAsynchronous(true);
}
mH.sendMessage(msg);
}
sendMessageとは,Messageを構築し,HタイプのHandlerを介して送信することである.Hの定義を見てみましょう.
ActivityThread.java
private class 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 handleMessage(Message msg) {
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;
...
}
}
...
}
HタイプのHandlerでは様々なタイプのメッセージが処理され、関数handleLaunchActivityでLAUNCH_が処理されるACTIVITYメッセージ:
ActivityThread.java
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
WindowManagerGlobal.initialize();
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
Bundle oldState = r.state;
handleResumeActivity(r.token, false, r.isForward, !r.activity.mFinished && !r.startsNotResumed);
if (!r.activity.mFinished && r.startsNotResumed) {
try {
r.activity.mCalled = false;
mInstrumentation.callActivityOnPause(r.activity);
...
}
...
}
} else {
...
}
}
ここには主に3つの操作が含まれており、performLaunchActivityはActivityを起動し、handleResumeActivityはResume Activityに来て、最後にInstrumentationのcallActivity OnPause関数を通じてOnPause Activityになります.performLaunchActivityの実装を見てみましょう.
ActivityThread.java
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
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);
}
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);
}
}
try {
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (activity != null) {
Context appContext = createBaseContextForActivity(r, activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
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);
if (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}
activity.mCalled = false;
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
if (!activity.mCalled) {
throw new SuperNotCalledException( "Activity " + r.intent.getComponent().toShortString() + " did not call through to super.onCreate()");
}
r.activity = activity;
r.stopped = true;
if (!r.activity.mFinished) {
activity.performStart();
r.stopped = false;
}
if (!r.activity.mFinished) {
if (r.isPersistable()) {
if (r.state != null || r.persistentState != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state, r.persistentState);
}
} else if (r.state != null) {
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
}
}
if (!r.activity.mFinished) {
activity.mCalled = false;
if (r.isPersistable()) {
mInstrumentation.callActivityOnPostCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnPostCreate(activity, r.state);
}
if (!activity.mCalled) {
throw new SuperNotCalledException("Activity " + r.intent.getComponent().toShortString() + " did not call through to super.onPostCreate()");
}
}
}
r.paused = true;
mActivities.put(r.token, r);
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException("Unable to start activity " + component + ": " + e.toString(), e);
}
}
return activity;
}
まずjavaを通ります.lang.ClassLoaderは、InstrumentationのnewActivityメソッドを呼び出し、Activityの名前に従ってActivityクラスをロードします.
Instrumentation.java
public Activity newActivity(ClassLoader cl, String className, Intent intent)
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
return (Activity)cl.loadClass(className).newInstance();
}
次に、ActivityのcontextをcreateBaseContextForActivityで生成し、activityを介して生成する.attachメソッドは、Activityのcontextおよびその他の属性をActivityに割り当てます.次にInstrumentationのcallActivity OnCreateメソッド、callActivity OnRestoreInstanceStateメソッド、callActivity OnPostCreateメソッドを呼び出し、それぞれActivityのonCreateメソッド、onRestoreInstanceStateメソッド、onPostCreateメソッドに対応します.これにより、performLaunchActivity関数でActivityのロードと初期化プロセスが完了します.
handleLaunchActivity関数に戻り、performLaunchActivityが完了した後、handleResumeActivityメソッドによりActivityがonResumeの準備を完了し、onResume状態に入る.最後に、InstrumentationのcallActivity OnPauseメソッドを呼び出し、ActivityをonPauseの状態にします.これにより、Activityが最終的に表示されると、onResumeから開始します.これでActivityのロードが完了しました.