Activity的工作过程

序入口函数,ActivityThread的main()函数

public static void main(String[] args) {
   //此处省略N行.......
   //创建Lopper,主线程Looper
    Looper.prepareMainLooper();
   //创建ActivityThread对象
    ActivityThread thread = new ActivityThread();
   //false,首次启动,需要初始化
    thread.attach(false);

    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }
    if (false) {
        Looper.myLooper().setMessageLogging(new
                LogPrinter(Log.DEBUG, "ActivityThread"));
    }
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
 // 主线程looper,开启死循环,不断处理按键、触摸等消息,activity的生命周期也由其处理
//若在activity的某个生命周期执行耗时操作,那么其他的消息无法及时执行,那么整个loop循环会卡顿
//时间一长,就会触发抛出ANR
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");

attach()分析

private void attach(boolean system) {
    sCurrentActivityThread = this;
    mSystemThread = system;
   //main入口传入的fasle
    if (!system) {
     //先走该分支代码
    //先获取ActivityManagerService对象,调用ActivityManagerService的attachApplication()
      final IActivityManager mgr = ActivityManagerNative.getDefault();
            try {
           // ======= 展开分析1 ========
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        //此处省略N行代码
    } else {
        try {
   //Instrumentation类会在应用的任何代码执行前被实列化,用来监控系统与应用的交互
  //另一个重要作用是提供Android组件单元测试。
            mInstrumentation = new Instrumentation();
          //应用进程conext创建 ====== 展开分析2 =======
            ContextImpl context = ContextImpl.createAppContext(
                    this, getSystemContext().mPackageInfo);
、       //创建mInitialApplication ===== 展开分析3 ========
            mInitialApplication = context.mPackageInfo.makeApplication(true, null);
            mInitialApplication.onCreate();
        } catch (Exception e) {
            throw new RuntimeException(
                    "Unable to instantiate Application():" + e.toString(), e);
        }
    }
    DropBox.setReporter(new DropBoxReporter());
    ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {
        @Override
        public void onConfigurationChanged(Configuration newConfig) {
            synchronized (mResourcesManager) {
               //立即将此更改应用于资源,因为在返回时,将查看视图层次结构。
                if (mResourcesManager.applyConfigurationToResourcesLocked(newConfig, null)) {
                    updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
                            mResourcesManager.getConfiguration().getLocales());
                    //资源被更改,发送消息通知
                    if (mPendingConfiguration == null ||
                            mPendingConfiguration.isOtherSeqNewer(newConfig)) {
                        mPendingConfiguration = newConfig;
                        sendMessage(H.CONFIGURATION_CHANGED, newConfig);
                    }
                }
            }
        }
        @Override
        public void onLowMemory() {
        }
        @Override
        public void onTrimMemory(int level) {
        }
    });

====展开分析1 ======

ActivityManagerNative,抽象类,一个Binder通信类
检索系统的默认/全局活动管理器。

static public IActivityManager getDefault() {
   //这里返回的是ActivityManagerService,继承自ActivityManagerService
    return gDefault.get();
}

最终调用ActivityManagerService内的attachAppliocation()

  @Override
    public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final long origId = Binder.clearCallingIdentity();
            attachApplicationLocked(thread, callingPid);
            Binder.restoreCallingIdentity(origId);
        }
    }

进入attachAoolicationLockede()

boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
        final String processName = app.processName;
        boolean didSomething = false;
     //遍历activity栈,找到栈顶的Activity
        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
                final ActivityStack stack = stacks.get(stackNdx);
                if (!isFrontStack(stack)) {
                    continue;
                }
               //解锁
                ActivityRecord hr = stack.topRunningActivityLocked(null);
                if (hr != null) {
                    if (hr.app == null && app.uid == hr.info.applicationInfo.uid
                            && processName.equals(hr.processName)) {
                        try {
                         //找到符合条件的Activity,真正启动Activity
                            if (realStartActivityLocked(hr, app, true, true)) {
                                didSomething = true;
                            }
                        } catch (RemoteException e) {
                          //此处省略N行......
                        }
                    }
                }
            }
        }
        //此处省略N行......
        return didSomething;
    }

realStartActivityLocked()内调用了ActivityThread的scheduleLaunchActivity()
此处给Activity赋值了各种信息,如token,在Android的Window机制中,添加Dailog、View会校验token,因此这边也会将token信息携带下去。
(如:"Unable to add window -- token " + attrs.token + " is not valid; is your activity running?这类token异常。关于这块可以去了解一下窗口机制)
此段代码最重要的是最后面的sendMessage。这里发送了一个消息,交给一个名为H的handler处理。H这个handler几乎处理所有Activity的生命周期的方法。

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) {
            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);
    //发送启动Activity的消息,使用内部继承Handelr的H,在ActivityThread创建时初始化
            sendMessage(H.LAUNCH_ACTIVITY, r);
        }

来看一下H的处理
handleMessage内调用handleLaunchActivity()

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, "LAUNCH_ACTIVITY");
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                } bre
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
        unscheduleGcIdler();
    //此处省略N行.........
           //初始化WindowManagerGlobal
        WindowManagerGlobal.initialize();
     // ========  performLaunchActivity()内部    ============
        //1.加载Activity的class类,执行其attach()
       //2.调用mInstrumentation.callActivityOnCreate,最终调用Activity的onCreate()
       //3.调用Activity的start()方法
        Activity a = performLaunchActivity(r, customIntent);
        if (a != null) {
            r.createdConfig = new Configuration(mConfiguration);
            reportSizeConfigurations(r);
            Bundle oldState = r.state;
   // =========  handleResumeActivity()内部      ==============
    //1.获取window,创建DecorView对象
    //2.获取windowManager,将DecorView添加到wm,此时开启view的测量,布局,绘制等等
   //3.使Activity可见
            handleResumeActivity(r.token, false, r.isForward,
                    !r.activity.mFinished && !r.startsNotResumed, r.lastProcessedSeq, reason);
            if (!r.activity.mFinished && r.startsNotResumed) {
                performPauseActivityIfNeeded(r, reason);
                if (r.isPreHoneycomb()) {
                    r.state = oldState;
                }
            }
        } else {
            try {
                ActivityManagerNative.getDefault()
                    .finishActivity(r.token, Activity.RESULT_CANCELED, null,
                            Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
        }
    }

====展开分析2 ======
ContextImpl(继承自Context)的构造方法,所以返回的是Context
简要看下一源码,针对Context的分析,后续会展开一篇文章,有兴趣的话,可以关注我~~

static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
    if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
    return new ContextImpl(null, mainThread,
            packageInfo, null, null, 0, null, null, Display.INVALID_DISPLAY);
}
private ContextImpl(ContextImpl container, ActivityThread mainThread,
        LoadedApk packageInfo, IBinder activityToken, UserHandle user, int flags,
        Display display, Configuration overrideConfiguration, int createDisplayWithId) {
    mOuterContext = this;
  //如果创建者没有指定使用哪个存储,则使用默认的应用程序位置。
    if ((flags & (Context.CONTEXT_CREDENTIAL_PROTECTED_STORAGE
            | Context.CONTEXT_DEVICE_PROTECTED_STORAGE)) == 0) {
       //此处省略N行代码
    }
  //传入ActvityThread
    mMainThread = mainThread;
  //传入activityToken
    mActivityToken = activityToken;
    mFlags = flags;
    if (user == null) {
        user = Process.myUserHandle();
    }
    mUser = user;
    mPackageInfo = packageInfo;
    //初始化ResourcesManager实例,用以获取资源文件
    mResourcesManager = ResourcesManager.getInstance();
   ///此处省略N行代码...........
}

======展开分析3 =========
LoadApk类,调用makeApplication()入参(true,null)。

public Application makeApplication(boolean forceDefaultAppClass,
        Instrumentation instrumentation) {
     //此处省略N行............
    try {
        java.lang.ClassLoader cl = getClassLoader();
     //此处省略N行............
        ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
       //通过mInstrumentation创建Application  
      // 
======= 展开分析4  =========
       app = mActivityThread.mInstrumentation.newApplication(
                cl, appClass, appContext);
        appContext.setOuterContext(app);
    } catch (Exception e) {
       //此处省略N行............
    }
    mActivityThread.mAllApplications.add(app);
    mApplication = app;
    if (instrumentation != null) {
        try {
            instrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {
           //此处省略N行............
    }
  //此处省略N行............
    return app;
}

=======展开分析4=======

Instrumetation类,创建Application,调用attach(context)
public Application newApplication(ClassLoader cl, String className, Context context)
        throws InstantiationException, IllegalAccessException, 
        ClassNotFoundException {
    return newApplication(cl.loadClass(className), context);
}
static public Application newApplication(Class<?> clazz, Context context)
        throws InstantiationException, IllegalAccessException, 
        ClassNotFoundException {
    Application app = (Application)clazz.newInstance();
    app.attach(context);
    return app;
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容