zoukankan      html  css  js  c++  java
  • 《转》深入理解Activity启动流程(三)–Activity启动的详细流程2

    本文原创作者:Cloud Chou. 出处:本文链接

    本系列博客将详细阐述Activity的启动流程,这些博客基于Cm 10.1源码研究。

    上篇博客介绍了Activity详细启动流程的前半部分:

    • 1. Activity调用ActivityManagerService启动应用
    • 2. ActivityManagerService调用Zygote孵化应用进程
    • 3. Zygote孵化应用进程

    本篇博客主要介绍Activity详细启动流程的后半部分:

    • 4. 新进程启动ActivityThread
    • 5. 应用进程绑定到ActivityManagerService
    • 6. ActivityThread的Handler处理启动Activity的消息

    4. 新进程启动ActivityThread

    点击图片可看大图

    zygote_activitythread

    Zygote进程孵化出新的应用进程后,会执行ActivityThread类的main方法。在该方法里会先准备好Looper和消息队列,然后调用attach方法将应用进程绑定到ActivityManagerService,然后进入loop循环,不断地读取消息队列里的消息,并分发消息。

    //ActivityThread类
    public static void main(String[] args) {
        //... 
        Looper.prepareMainLooper();
        ActivityThread thread = new ActivityThread();
        thread.attach(false);
    
        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }
        AsyncTask.init();
        //...
        Looper.loop();
    
        //...
    }

    5. 应用进程绑定到ActivityManagerService

    点击图片可看大图

    application_amservice

    在ActivityThread的main方法里调用thread.attach(false);attach方法的主要代码如下所示:

    //ActivityThread类
    private void attach(boolean system) {
        sThreadLocal.set(this);
        mSystemThread = system;
        if (!system) {
            //...
            IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
            //调用ActivityManagerService的attachApplication方法
            //将ApplicationThread对象绑定至ActivityManagerService,
            //这样ActivityManagerService就可以
            //通过ApplicationThread代理对象控制应用进程
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                // Ignore
            }
        } else {
            //...
        }
        //... 
    }

    ActivityManagerService的attachApplication方法执行attachApplicationLocked(thread, callingPid)进行绑定。

    //ActivityManagerService类
    private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) { 
        ProcessRecord app;
        //...     
        app.thread = thread; 
        //...  
        try {
            //...
            thread.bindApplication(processName, appInfo, providers,
                    app.instrumentationClass, profileFile, profileFd, profileAutoStop,
                    app.instrumentationArguments, app.instrumentationWatcher, testMode,
                    enableOpenGlTrace, isRestrictedBackupMode || !normalMode, app.persistent,
                    new Configuration(mConfiguration), app.compat, getCommonServicesLocked(),
                    mCoreSettingsObserver.getCoreSettingsLocked());
            //... 
        } catch (Exception e) {
           //...
        }
        //... 
        ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
        if (hr != null && normalMode) {
            if (hr.app == null && app.uid == hr.info.applicationInfo.uid
                    && processName.equals(hr.processName)) {
                try {
                    if (mHeadless) {
                        Slog.e(TAG, "Starting activities not supported on headless device: " + hr);
                    } else if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
                    //mMainStack.realStartActivityLocked真正启动activity
                        didSomething = true;
                    }
                } catch (Exception e) {
                    //...
                }
            } else {
                //...
            }
        }
        //... 
        return true;
    }

    attachApplicationLocked方法有两个重要的函数调用thread.bindApplication和mMainStack.realStartActivityLocked。thread.bindApplication将应用进程的ApplicationThread对象绑定到ActivityManagerService,也就是说获得ApplicationThread对象的代理对象。mMainStack.realStartActivityLocked通知应用进程启动Activity。

    5.1 thread.bindApplication

    thread对象其实是ActivityThread里ApplicationThread对象在ActivityManagerService的代理对象,故此执行thread.bindApplication,最终会调用ApplicationThread的bindApplication方法,该方法的主要代码如下所示:

    //ActivityThread类
    public final void bindApplication(String processName,
            ApplicationInfo appInfo, List<ProviderInfo> providers,
            ComponentName instrumentationName, String profileFile,
            ParcelFileDescriptor profileFd, boolean autoStopProfiler,
            Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
            int debugMode, boolean enableOpenGlTrace, boolean isRestrictedBackupMode,
            boolean persistent, Configuration config, CompatibilityInfo compatInfo,
            Map<String, IBinder> services, Bundle coreSettings) {
        //...  
        AppBindData data = new AppBindData();
        data.processName = processName;
        data.appInfo = appInfo;
        data.providers = providers;
        data.instrumentationName = instrumentationName;
        data.instrumentationArgs = instrumentationArgs;
        data.instrumentationWatcher = instrumentationWatcher;
        data.debugMode = debugMode;
        data.enableOpenGlTrace = enableOpenGlTrace;
        data.restrictedBackupMode = isRestrictedBackupMode;
        data.persistent = persistent;
        data.config = config;
        data.compatInfo = compatInfo;
        data.initProfileFile = profileFile;
        data.initProfileFd = profileFd;
        data.initAutoStopProfiler = false;
        queueOrSendMessage(H.BIND_APPLICATION, data);
    }

    这样调用queueOrSendMessage会往ActivityThread的消息队列发送消息,消息的用途是BIND_APPLICATION。

    这样会在handler里处理BIND_APPLICATION消息,接着调用handleBindApplication方法处理绑定消息。

    //ActivityThread类
    private void handleBindApplication(AppBindData data) {
      //...  
      ApplicationInfo instrApp = new ApplicationInfo();
      instrApp.packageName = ii.packageName;
      instrApp.sourceDir = ii.sourceDir;
      instrApp.publicSourceDir = ii.publicSourceDir;
      instrApp.dataDir = ii.dataDir;
      instrApp.nativeLibraryDir = ii.nativeLibraryDir;
      LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
            appContext.getClassLoader(), false, true);
      ContextImpl instrContext = new ContextImpl();
      instrContext.init(pi, null, this);
        //... 
       
         
    
      if (data.instrumentationName != null) {
           //...
      } else {
           //注意Activity的所有生命周期方法都会被Instrumentation对象所监控,
           //也就说执行Activity的生命周期方法前后一定会调用Instrumentation对象的相关方法
           //并不是说只有跑单测用例才会建立Instrumentation对象,
           //即使不跑单测也会建立Instrumentation对象
           mInstrumentation = new Instrumentation();
      }
      //... 
      try {
         //...
         Application app = data.info.makeApplication(data.restrictedBackupMode, null);
         mInitialApplication = app;
         //...         
         try {
              mInstrumentation.onCreate(data.instrumentationArgs);
          }catch (Exception e) {
                 //...
          }
          try {
               //这里会调用Application的onCreate方法
               //故此Applcation对象的onCreate方法会比ActivityThread的main方法后调用
               //但是会比这个应用的所有activity先调用
                mInstrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {
               //...
            }
        } finally {
            StrictMode.setThreadPolicy(savedPolicy);
        }
    }

    5.2 mMainStack.realStartActivityLocked

    realStartActivity会调用scheduleLaunchActivity启动activity,主要代码:

    //ActivityStack类
    final boolean realStartActivityLocked(ActivityRecord r,
            ProcessRecord app, boolean andResume, boolean checkConfig)
            throws RemoteException {
    
        //...  
        try {
            //...
            app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info,
                    new Configuration(mService.mConfiguration),
                    r.compat, r.icicle, results, newIntents, !andResume,
                    mService.isNextTransitionForward(), profileFile, profileFd,
                    profileAutoStop);
            
            //...
            
        } catch (RemoteException e) {
            //...
        }
        //...    
        return true;
    }

    同样app.thread也只是ApplicationThread对象在ActivityManagerService的一个代理对象而已,最终会调用ApplicationThread的scheduleLaunchActivity方法。

    //ActivityThread类
    public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
            ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
            Bundle state, List<ResultInfo> pendingResults,
            List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
            String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
        ActivityClientRecord r = new ActivityClientRecord();
        r.token = token;
        r.ident = ident;
        r.intent = intent;
        r.activityInfo = info;
        r.compatInfo = compatInfo;
        r.state = state;
        r.pendingResults = pendingResults;
        r.pendingIntents = pendingNewIntents;
        r.startsNotResumed = notResumed;
        r.isForward = isForward;
        r.profileFile = profileName;
        r.profileFd = profileFd;
        r.autoStopProfiler = autoStopProfiler;
        updatePendingConfiguration(curConfig);
        queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
    }

    这里调用了queueOrSendMessage往ActivityThread的消息队列发送了消息,消息的用途是启动Activity,接下来ActivityThread的handler便会处理该消息。

    6. ActivityThread的Handler处理启动Activity的消息

    点击图片可看大图

    activitythread_activity

    ActivityThread的handler调用handleLaunchActivity处理启动Activity的消息,handleLaunchActivity的主要代码如下所示:

    //ActivityThread类
    private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        //... 
        Activity a = performLaunchActivity(r, customIntent);
        if (a != null) {
            //...
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed);
            //...
        } else {
            //...
        }
    }

    handleLaunchActivity方法里有有两个重要的函数调用,performLaunchActivity和handleResumeActivity,performLaunchActivity会调用Activity的onCreate,onStart,onResotreInstanceState方法,handleResumeActivity会调用Activity的onResume方法.

    6.1 performLaunchActivity

    performLaunchActivity的主要代码如下所示:

    //ActivityThread类
    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);
            //...
        } catch (Exception e) {
            //...
        }
        try {
            //r.packageInfo.makeApplication实际并未创建Application对象,
            //因为bindApplication过程已经创建了Application对象,
            //makeApplication方法会返回已创建的Application对象
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);
            //...         
            if (activity != null) {
                //...
                //将application对象,appContext对象绑定到新建的activity对象
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config);
                //... 
                //会调用Activity的onCreate方法             
                mInstrumentation.callActivityOnCreate(activity, r.state);
                //...
                //...
                //调用Activity的onStart方法
                if (!r.activity.mFinished) {
                    activity.performStart();
                    r.stopped = false;
                }              
                if (!r.activity.mFinished) {
                    if (r.state != null) {
                        //会调用Activity的onRestoreInstanceState方法
                        mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                    }
                }
                if (!r.activity.mFinished) {
                    activity.mCalled = false;
                    mInstrumentation.callActivityOnPostCreate(activity, r.state);
                    //...
                }
            }
            //...
        } catch (SuperNotCalledException e) {
            throw e;
    
        } catch (Exception e) {
            //...
        }
        return activity;
    }

    6.2 handleResumeActivity

    handleResumeActivity的主要代码如下所示:

    //ActivityThread类
    final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward,
            boolean reallyResume) {
        //...
        //performResumeActivity最终会调用Activity的onResume方法 
        ActivityClientRecord r = performResumeActivity(token, clearHide);
        if (r != null) {
            final Activity a = r.activity;
            //... 
            //显示界面
            if (r.window == null && !a.mFinished && willBeVisible) {
                r.window = r.activity.getWindow();
                View decor = r.window.getDecorView();
                decor.setVisibility(View.INVISIBLE);
                ViewManager wm = a.getWindowManager();
                WindowManager.LayoutParams l = r.window.getAttributes();
                a.mDecor = decor;
                l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
                l.softInputMode |= forwardBit;
                if (a.mVisibleFromClient) {
                    a.mWindowAdded = true;
                    wm.addView(decor, l);
                }
               //...         
            } else if (!willBeVisible) {
                 //...
            }
            // Tell the activity manager we have resumed.
            if (reallyResume) {
                try {
                    ActivityManagerNative.getDefault().activityResumed(token);
                } catch (RemoteException ex) {
                }
            }
    
        } else {
             //...
        }
    }

    performResumeActivity的主要代码如下所示:

    //ActivityThread类
    public final ActivityClientRecord performResumeActivity(IBinder token,
            boolean clearHide) {
        ActivityClientRecord r = mActivities.get(token);
        //...
        if (r != null && !r.activity.mFinished) {
             //...
            try {
                //... 
                //会调用Activity的onResume方法 
                r.activity.performResume();
                //...
            } catch (Exception e) {
                //...
            }
        }
        return r;
    }

    总结

    Activity的概要启动流程:

    用户在Launcher程序里点击应用图标时,会通知ActivityManagerService启动应用的入口Activity,ActivityManagerService发现这个应用还未启动,则会通知Zygote进程孵化出应用进程,然后在这个dalvik应用进程里执行ActivityThread的main方法。应用进程接下来通知ActivityManagerService应用进程已启动,ActivityManagerService保存应用进程的一个代理对象,这样ActivityManagerService可以通过这个代理对象控制应用进程,然后ActivityManagerService通知应用进程创建入口Activity的实例,并执行它的生命周期方法

    现在也可以理解:

    如果应用的组件(包括所有组件Activity,Service,ContentProvider,Receiver) 被启动,肯定会先启动以应用包名为进程名的进程,这些组件都会运行在应用包名为进程名的进程里,并且是在主线程里。应用进程启动时会先创建Application对象,并执行Application对象的生命周期方法,然后才启动应用的组件。

    有一种情况比较特殊,那就是为组件设置了特殊的进程名,也就是说通过android:process设置进程名的情况,此时组件运行在单独的进程内。

    下篇博客将介绍Activity,Task的调度算法。

  • 相关阅读:
    javascript的字段值,私有变量,静态方法声明
    取得序列中某个点的范围边界
    使用wubi安装ubuntu11.04后无线网卡被禁用无法打开解决办法
    WEB前端性能优化
    jQuery的arrayLike
    在手机上安装BT5系统,没错就是破解无线密码的那个
    PHP在子类方法B调用父类的方法A时,不传参数时仍能得到方法B的名称
    讨厌的文本选区
    PHP遍历解析XML为一个数组
    “软工厂代码生成工具”的学习笔记
  • 原文地址:https://www.cnblogs.com/andy2simple/p/6740066.html
Copyright © 2011-2022 走看看