Android中Activity启动源码分析

今天工作中,想监控Activity加载时间,同事给提供了两种方式。

1、在onCreate和onPostResume方法中记录时间

2、在onCreate记录开始时间,并创建Handler,调用post方法,在post中记录结束时间

方式一很简单,但因为记录时间代码是动态注入到Activity的儿子节点,所以如果孙子节点等,如果在onPostResume中有自己的代码,就无法统计到,不过这种情况很少。

方式二,利用了ActivityThread中的消息机制,后面详细介绍。

首先,要了解下Activity的启动流程:(android-23)

启动Activity,都是通过startActivity开始的;点击图标,其实就是通过Lancher程序启动另一个程序的Activity。

android.app.Activity.java

public class Activity extends ContextThemeWrapper
        implements LayoutInflater.Factory2,
        Window.Callback, KeyEvent.Callback,
        OnCreateContextMenuListener, ComponentCallbacks2,
        Window.OnWindowDismissedCallback {

    ..............................................................

    /**
     * Same as {@link #startActivity(Intent, Bundle)} with no options
     * specified.
     *
     * @param intent The intent to start.
     *
     * @throws android.content.ActivityNotFoundException
     *
     * @see {@link #startActivity(Intent, Bundle)}
     * @see #startActivityForResult
     */
    @Override
    public void startActivity(Intent intent) {
        startActivity(intent, null);
    }

    ...............................................................

    public void startActivityForResult(Intent intent, int requestCode, @Nullable 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;
            }

            final View decor = mWindow != null ? mWindow.peekDecorView() : null;
            if (decor != null) {
                decor.cancelPendingInputEvents();
            }
            // TODO Consider clearing/flushing other event sources and events for child windows.
        } 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);
            }
        }
        if (options != null && !isTopOfTask()) {
            mActivityTransitionState.startExitOutTransition(this, options);
        }
    }
}

下面来看android.app.Instrumentation.java

public class Instrumentation {

	......

	public ActivityResult execStartActivity(
	            Context who, IBinder contextThread, IBinder token, Activity target,
	            Intent intent, int requestCode) {
		IApplicationThread whoThread = (IApplicationThread) contextThread;
		if (mActivityMonitors != null) {
			......
		}
		try {
			int result = ActivityManagerNative.getDefault()
				.startActivity(whoThread, intent,
				intent.resolveTypeIfNeeded(who.getContentResolver()),
				null, 0, token, target != null ? target.mEmbeddedID : null,
				requestCode, false, false);
			......
		} catch (RemoteException e) {
		}
		return null;
	}

	......

}

ActivityManagerNative是一个抽象类,并且继承了Binder。这里的ActivityManagerNative.getDefault返回ActivityManagerService的远程接口,即ActivityManagerProxy接口。

public abstract class ActivityManagerNative extends Binder implements IActivityManager
{
    /**
     * Cast a Binder object into an activity manager interface, generating
     * a proxy if needed.
     */
    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);
    }

    /**
     * Retrieve the system's default/global activity manager.
     */
    static public IActivityManager getDefault() {
        return gDefault.get();
    }
    …………………………
}

这中间的调用就不详细介绍了,可以参考下面两篇博客

http://blog.csdn.net/abcdef314159/article/details/50962335

http://blog.csdn.net/luoshengyang/article/details/6689748

最终会调用到ApplicationThread的schedulePauseActivity和scheduleLaunchActivity

public final class ActivityThread {

    final H mH = new H();

    private class ApplicationThread extends ApplicationThreadNative {
        // we use token to identify this activity without having to send the
        // activity itself back to the activity manager. (matters more with ipc)
        @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);
        }

    }

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

下面来看下Handler中的处理

    private class H extends Handler {
        public static final int LAUNCH_ACTIVITY         = 100;
        …………………………
        public void 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");
                    ActivityClientRecord r = (ActivityClientRecord)msg.obj;

                    r.packageInfo = getPackageInfoNoCheck(
                            r.activityInfo.applicationInfo, r.compatInfo);
                    handleLaunchActivity(r, null);
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } break;
               …………………………
            }
    }

继续查看handleLaunchActivity方法

    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    	…………………………
        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);
            …………………………
                r.paused = true;
            }
        } else {
        	…………………………
        }
    }

可以看到会处理performLaunchActivity和handleResumeActivity

    private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    	…………………………
        Activity activity = null;
        try {
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
            //创建Activity
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
          …………………………

        try {
            //创建Application
        	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);
                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                        + r.activityInfo.name + " with config " + config);
                //调用Activity的attach方法,这个我们在前面讲的时候也多次提及
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config);

                …………………………
                int theme = r.activityInfo.getThemeResource();
                if (theme != 0) {
                   // 设置主题
                	activity.setTheme(theme);
                }

                //调用Activity的OnCreate方法,
                mInstrumentation.callActivityOnCreate(activity, r.state);
               …………………………
                if (!r.activity.mFinished) {
                    //调用Activity的onStart方法
                	activity.performStart();
                    r.stopped = false;
                }
                if (!r.activity.mFinished) {
                    if (r.state != null) {
                       //调用Activity的OnRestoreInstanceState方法
                    	mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                    }
                }
               …………………………
        return activity;
    }

由源码看到,会执行onCreate、onPostCreate、onStart、onRestoreInstance方法

执行完后,会执行onResume方法

再看下Looper的源码

   /**
     * Run the message queue in this thread. Be sure to call
     * {@link #quit()} to end the loop.
     */
    public static void loop() {
        final Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        final MessageQueue queue = me.mQueue;

        // Make sure the identity of this thread is that of the local process,
        // and keep track of what that identity token actually is.
        Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();

        for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }

            // This must be in a local variable, in case a UI event sets the logger
            Printer logging = me.mLogging;
            if (logging != null) {
                logging.println(">>>>> Dispatching to " + msg.target + " " +
                        msg.callback + ": " + msg.what);
            }

            msg.target.dispatchMessage(msg);

            if (logging != null) {
                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
            }

            // Make sure that during the course of dispatching the
            // identity of the thread wasn't corrupted.
            final long newIdent = Binder.clearCallingIdentity();
            if (ident != newIdent) {
                Log.wtf(TAG, "Thread identity changed from 0x"
                        + Long.toHexString(ident) + " to 0x"
                        + Long.toHexString(newIdent) + " while dispatching to "
                        + msg.target.getClass().getName() + " "
                        + msg.callback + " what=" + msg.what);
            }

            msg.recycle();
        }
    }

再看下Looper打印的log,使用下面代码设置Looper的log输出

Looper.getMainLooper().setMessageLogging(new LooperPrint());

《Android中Activity启动源码分析》

从日志可以看出,100即是LAUNCH_ACTIVITY,只有执行完所有launch代码,才会执行我们自己的post方法。

    @Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		Log.e(TAG, "onCreate before super");
		Handler handler = new Handler();
		handler.post(new Runnable() {
			@Override
			public void run() {
				// TODO Auto-generated method stub
				Log.e(TAG, "handler.post");
			}
		});
		super.onCreate(savedInstanceState);
	}

贴一下自己整理的流程图

https://my.oschina.net/android520/blog/818603

    原文作者:移动开发
    原文地址: https://my.oschina.net/android520/blog/693376
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞