• Android进阶系列之源码分析Activity的启动流程


    itdadao

    美女镇楼,辟邪!

    源码,是一个程序猿前进路上一个大的而又不得不去翻越障碍,我讨厌源码,看着一大堆。5000多行,要看完得啥时候去了啊。不过做安卓的总有这一天,自从踏上这条不归路,我就认命了。好吧,我慢慢来啃。先从Activity的启动流程开始,一个app启动的底层源码流程。那么我们该去哪里找源码呢,源码其实就在sdk的包里,并不遥远,只是平时我们很少去关注。(从应用层的入口开始,FrameWork层目前我还没那水平,看不明白),如果想从FrameWork层开始的童鞋,这里给个链接,去看看吧。http://www.jianshu.com/p/6037f6fda285,还有老罗讲Activity启动的更详细步骤,可以参考阅读:http://blog.csdn.net/luoshengyang/article/details/6689748

    首先找到sdk文件夹目录,打开source文件夹,我选的是android-21目录,在继续打开android文件夹,继续打开app文件夹,找到ActivityThread.java文件,这就是我们平时所说的UI线程(主线程)。

    itdadao

    图 1

    在打开Android Studio,直接把这个文件用鼠标拖入Studio界面即可。那么开始我们探索源码之路了。

    首先,找到整个java文件的入口,不用问大家都知道,main函数,是所有java文件的入口。直接ctrl+F,搜索main,找到入口。开始怼他!

    itdadao

    图2

    这里不对每句代码进行详细解释,我们只撸对Activity启动有作用的代码。用过Handler的童鞋都知道,Handler是线程之间通讯的工具。第5205行代码,Looper.prepareMianLooper();就是为UI线程绑定Looper和MessageQueue,一个线程中只能有一个Looper和一个MessageQueue,可以有多个Handler这也是为什么我们平时在Activity的住线程中使用Handler传送消息时,只需要创建Handler不需要管Looper和MessageQueue的原因。

    我们只需关心主线程做了哪些操作,其他的先不管。第5207行代码创建了ActivityThread的对象,同时调用了一个attach传入一个false。那么找到attach方法。

    itdadao

    图3

    初始化传入的是false,那么只看if(!system)里的代码,继续寻找和Activity有关的代码,看到5054行代码,创建了一个ActivityManager,这是Activity的管理器,那么我们在看看ActivityManagerNative这个类的getDefault()这个方法,默认返回的ActivityManager里有什么样的配置。找到源码包,搜索ActivityManagerNative,拖入Studio。

    itdadao

    图4

    这里通过gDefault对象的get()返回IActivityManager,那么看看gDefault又是什么呢。

    itdadao

    图5

    这里采用IBinder机制,通过ServiceManager获得activity的服务,调用asInterface(IBinder)方法,获得IActivityManager。再看看asInterface()方法。

    itdadao

    图6

    这里最后返回的是一个ActivityManagerProxy对象,通过代理设计模式来创建实现了IActivityManager接口的类的对象。

    再回到图3ActivityThread中,获得了ActivityManager之后,第5056行调用attachApplication(),传入applicationThread类型的Binder对象。那么看一下ActivityManagerProxy的源码。

    class ActivityManagerProxy implements IActivityManager
    {
    	......
    
    	public void attachApplication(IApplicationThread app) throws RemoteException
    	{
    		Parcel data = http://blog.csdn.net/sw5131899/article/details/Parcel.obtain();
    		Parcel reply = Parcel.obtain();
    		data.writeInterfaceToken(IActivityManager.descriptor);
    		data.writeStrongBinder(app.asBinder());
    		mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0);
    		reply.readException();
    		data.recycle();
    		reply.recycle();
    	}
    
    	......
    
    }

    这里通过Binder驱动程序,最后进入ActivityManagerService的attachApplication函数中。那么我们看看ActivityManagerService中的attachApplication函数。

    itdadao

    图7

    在这个方法中调用了attachApplicationLocked()方法,这里将操作转发给attachApplicationLocked函数。

    public final class ActivityManagerService extends ActivityManagerNative  
            implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {  
      
        ......  
      
        private final boolean attachApplicationLocked(IApplicationThread thread,  
                int pid) { http://www.90168.org/ 
            // Find the application record that is being attached...  either via  
            // the pid if we are running in multiple processes, or just pull the  
            // next app record if we are emulating process with anonymous threads.  
            ProcessRecord app;  
            if (pid != MY_PID && pid >= 0) {  
                synchronized (mPidsSelfLocked) {  
                    app = mPidsSelfLocked.get(pid);  
                }  
            } else if (mStartingProcesses.size() > 0) {  
                ......  
            } else {  
                ......  
            }  
      
            if (app == null) {  
                ......  
                return false;  
            }  
      
            ......  
      
            String processName = app.processName;  
            try {  
                thread.asBinder().linkToDeath(new AppDeathRecipient(  
                    app, pid, thread), 0);  
            } catch (RemoteException e) {  
                ......  
                return false;  
            }  
      
            ......  
      
            app.thread = thread;  
            app.curAdj = app.setAdj = -100;  
            app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;  
            app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;  
            app.forcingToForeground = null;  
            app.foregroundServices = false;  
            app.debugging = false;  
      
            ......  
      
            boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);  
      
            ......  
      
            boolean badApp = false;  
            boolean didSomething = false;  
      
            // See if the top visible activity is waiting to run in this process...  
            ActivityRecord hr = mMainStack.topRunningActivityLocked(null);  
            if (hr != null && normalMode) {  
                if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid  
                    && processName.equals(hr.processName)) {  
                        try {  
                            if (mStackSupervisor.realStartActivityLocked(hr, app, true, true)) {  
                                didSomething = true;  
                            }  
                        } catch (Exception e) {  
                            ......  
                        }  
                } else {  
                    ......  
                }  
            }  
      
            ......  
      
            return true;  
        }  
      
        ......  
      
    }  

    这里创建了一个ProcessRecord,首先通过pid将它取回来,放在app变量中,然后对app的其它成员进行初始化,最后调用

    mStacksupervisor.realStartActivityLocked执行真正的Activity启动操作。这里要启动的Activity通过调用mStacksupervisor.topRunningActivityLocked(null)从堆栈顶端取回来,这时候在堆栈顶端的Activity就是MainActivity了。那么继续来看ActivityStackSupervisor.realStartActivityLocked()的源码.

    final boolean realStartActivityLocked(ActivityRecord r,
                ProcessRecord app, boolean andResume, boolean checkConfig)
                throws RemoteException {
    
    	....
            r.app = app;
            ....
            int idx = app.activities.indexOf(r);
            if (idx < 0) {
                app.activities.add(r);
            }
           ...
            try {
                if (app.thread == null) {
                    throw new RemoteException();
                }
                List<ResultInfo> results = null;
                List<Intent> newIntents = null;
                ...
                app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                        System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
                        r.compat, r.task.voiceInteractor, app.repProcState, r.icicle, r.persistentState,
                        results, newIntents, !andResume, mService.isNextTransitionForward(),
                        profilerInfo);
    
               .....
    
            } catch (RemoteException e) {
                ..
            }
    
           ...
    
            return true;
        }

     这里最终通过app.thread进入到ApplicationThreadProxy的scheduleLaunchActivity函数中,注意,这里的第二个参数r,是一个ActivityRecord类型的Binder对象,用来作来这个Activity的token值。app.thread.scheduleLaunchActivity调用的是ApplicationThreadProxy的方法,那么再看看ApplicationThreadProxy。

    class ApplicationThreadProxy implements IApplicationThread {  
      
        ......  
      
        public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,  
                ActivityInfo info, Bundle state, List<ResultInfo> pendingResults,  
                List<Intent> pendingNewIntents, boolean notResumed, boolean isForward)  
                throws RemoteException { www.90168.org 
            Parcel data = http://blog.csdn.net/sw5131899/article/details/Parcel.obtain();  
            data.writeInterfaceToken(IApplicationThread.descriptor);  
            intent.writeToParcel(data, 0);  
            data.writeStrongBinder(token);  
            data.writeInt(ident);  
            info.writeToParcel(data, 0);  
            data.writeBundle(state);  
            data.writeTypedList(pendingResults);  
            data.writeTypedList(pendingNewIntents);  
            data.writeInt(notResumed ? 1 : 0);  
            data.writeInt(isForward ? 1 : 0);  
            mRemote.transact(SCHEDULE_LAUNCH_ACTIVITY_TRANSACTION, data, null,  
                IBinder.FLAG_ONEWAY);  
            data.recycle();  
        }  
      
        ......  
      
    }  

     函数首先创建一个ActivityClientRecord实例,并且初始化它的成员变量,然后调用ActivityThread类的queueOrSendMessage函数进一步处理。那么再来看看ActivityThread源码的queueOrSendMessage。

    public final class ActivityThread {  
      
        ......  
      
        private final class ApplicationThread extends ApplicationThreadNative {  
      
            ......  
      
            // if the thread hasn't started yet, we don't have the handler, so just  
            // save the messages until we're ready.  
            private final void queueOrSendMessage(int what, Object obj) {  
                queueOrSendMessage(what, obj, 0, 0);  
            }  
      
            ......  
      
            private final void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {  
                synchronized (this) {  
                    ......  
                    Message msg = Message.obtain();  
                    msg.what = what;  
                    msg.obj = obj;  
                    msg.arg1 = arg1;  
                    msg.arg2 = arg2;  
                    mH.sendMessage(msg);  
                }  
            }  
      
            ......  
      
        }  
      
        ......  
    } 

     函数把消息内容放在msg中,然后通过mH把消息分发出去,这里的成员变量mH我们在前面已经见过,消息分发出去后,最后会调用H类的handleMessage函数。 itdadao 这里最后调用ActivityThread类的handleLaunchActivity函数进一步处理。再看看handleLaunchActivity();

    public final class ActivityThread {  
      
        ......  
      
        private final 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);  
      
                ......  
            } else {  
                ......  
            }  
        }  
      
        ......  
    }  

    这里首先调用performLaunchActivity函数来加载这个Activity类,即activity.MainActivity,然后调用它的onCreate函数,最后回到handleLaunchActivity函数时,再调用handleResumeActivity函数来使这个Activity进入Resumed状态,即会调用这个Activity的onResume函数,这是遵循Activity的生命周期的。再看performLaunchActivity的源码。

    public final class ActivityThread {  
      
        ......  
      
        private final Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {  
              
            ActivityInfo aInfo = r.activityInfo;  
            if (r.packageInfo == null) {  
                r.packageInfo = getPackageInfo(aInfo.applicationInfo,  
                    Context.CONTEXT_INCLUDE_CODE);  
            }  http://www.90168.org/
      
            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);  
                r.intent.setExtrasClassLoader(cl);  
                if (r.state != null) {  
                    r.state.setClassLoader(cl);  
                }  
            } catch (Exception e) {  
                ......  
            }  
      
            try {  
                Application app = r.packageInfo.makeApplication(false, mInstrumentation);  
      
                ......  
      
                if (activity != null) {  
                    ContextImpl appContext = new ContextImpl();  
                    appContext.init(r.packageInfo, r.token, this);  
                    appContext.setOuterContext(activity);  
                    CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());  
                    Configuration config = new Configuration(mConfiguration);  
                    ......  
                    activity.attach(appContext, this, getInstrumentation(), r.token,  
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,  
                        r.embeddedID, r.lastNonConfigurationInstance,  
                        r.lastNonConfigurationChildInstances, config);  
      
                    if (customIntent != null) {  
                        activity.mIntent = customIntent;  
                    }  
                    r.lastNonConfigurationInstance = null;  
                    r.lastNonConfigurationChildInstances = null;  
                    activity.mStartedActivity = false;  
                    int theme = r.activityInfo.getThemeResource();  
                    if (theme != 0) {  
                        activity.setTheme(theme);  
                    }  
      
                    activity.mCalled = false;  
                    mInstrumentation.callActivityOnCreate(activity, r.state);  
                    ......  
                    r.activity = activity;  
                    r.stopped = true;  
                    if (!r.activity.mFinished) {  
                        activity.performStart();  
                        r.stopped = false;  
                    }  
                    if (!r.activity.mFinished) {  
                        if (r.state != null) {  
                            mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);  
                        }  
                    }  
                    if (!r.activity.mFinished) {  
                        activity.mCalled = false;  
                        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) {  
                ......  
      
            } catch (Exception e) {  
                ......  
            }  
      
            return activity;  
        }  
      
        ......  
    } 

    从上面可以看到,mInrumentation.callActivityOncreate(),那么在这里进正式进入了Activity的onCreate()方法了。之后会依次调用Activity的生命周期方法。调用生命周期方法的类都是Intrumentation。

    到这里就差不多了,应用层从入口到Activity启动调用Activity的生命周期,当然中间也省略了一些不太重要的步骤。最后附一张流程图。

    itdadao

  • 相关阅读:
    clientHeight、offsetHeight、scrollHeight详解
    JavaScript中常见的字符串操作函数及用法
    获取伪元素的属性和改变伪元素的属性
    HTML和CSS实现左侧固定宽度右侧内容可滚动
    gulp常用插件
    gulp入门详细教程
    Javascript 异步实现机制
    JavaScript:彻底理解同步、异步和事件循环(Event Loop)
    chrome调试,打完断点后关于JS的几个控制介绍
    js断点调试心得
  • 原文地址:https://www.cnblogs.com/tianshifu/p/6214900.html
Copyright © 2020-2023  润新知