Android 中你碰不到但是很重要的类之ActivityThread

 private void handleBindApplication(AppBindData data) {
        Application app;
        data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo, isSdkSandbox);//内部创建LoadedApk
        app = data.info.makeApplicationInner(data.restrictedBackupMode, null);//内部创建Applicaiton对象,调用onCreate()方法
        installContentProviders(app, data.providers); //cotentprovider初始化
        mInstrumentation.callApplicationOnCreate(app);//调用onCreate()方法
    }

  • 这里找到了为什么使用ContentProvider能够实现初始化,构建的时候会创建ContenProvider。
 public Activity newActivity(ClassLoader cl, String className,
            Intent intent)
            throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {
        String pkg = intent != null && intent.getComponent() != null
                ? intent.getComponent().getPackageName() : null;
        return getFactory(pkg).instantiateActivity(cl, className, intent);//加载创建Activity
    }

  • IActivityManager(binder):应用进程和SystemServer进程打交道的时候。
  • AppliactionThread(binder):SystemServer进程与应用进程通信。

2、为什么使用ContentProvider可以实现初始化

 private void handleBindApplication(AppBindData data) {
        Application app;
        data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo, isSdkSandbox);//内部创建LoadedApk
        app = data.info.makeApplicationInner(data.restrictedBackupMode, null);//内部创建Applicaiton对象,调用onCreate()方法
        installContentProviders(app, data.providers); //cotentprovider初始化
        mInstrumentation.callApplicationOnCreate(app);//调用onCreate()方法
    }

上一段分析时已经找打了答案,应用进程被拉起来之后,在创建Application对象调用attachBaseContext()和onCreate()方法之间会调用ContentProvider的onCreate()方法这也是很多第三方SDK使用该特性实现初始化的原理。

3、Activity是什么时候开始渲染的

  public void handleResumeActivity() {
        performResumeActivity(r, finalStateRequest, reason)//调用Activity onResume
        final Activity a = r.activity;
        View decor = r.window.getDecorView();
        ViewManager wm = a.getWindowManager();
        a.mWindowAdded = true;
        wm.addView(decor, l);
   }

ActivityThread.javahandleResumeActivity()有这样一段代码,我们可以得出结论,Activity渲染的起点是在 onResume阶段,在onResume阶段会把decorView交给WindowManager开始执行渲染。

4、原来还可以监控组件的生命周期

class H extends Handler {

    public static final int RECEIVER                = 113; //广播接收者

    @UnsupportedAppUsage
    public static final int CREATE_SERVICE          = 114;//Service创建

    public static final int INSTALL_PROVIDER        = 145;//ContentProvider

    public static final int RELAUNCH_ACTIVITY = 160; //Activity启动

   public void handleMessage(Message msg) {
        if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
        switch (msg.what) {
            case BIND_APPLICATION:
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
                AppBindData data = (AppBindData)msg.obj;
                handleBindApplication(data);
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                break;
            case RECEIVER:
                handleReceiver((ReceiverData)msg.obj);
                break;
            case CREATE_SERVICE:
                handleCreateService((CreateServiceData)msg.obj);
                break;
            case BIND_SERVICE:
                handleBindService((BindServiceData)msg.obj);
                break;

            case RELAUNCH_ACTIVITY:
                handleRelaunchActivityLocally((IBinder) msg.obj);
                break;
        }
    }
}

系统进程(system_server)指挥应用进程组件生命周期的第一站其实就在ActivityThread这里,交给H对象其实是主线程的Handler来分发处理,如上。我们可以反射拿到这一信息,可以监控到主线程对于这些组件调度的信息,这一信息对我们监控排查ANR很有帮助。

5 、SharedPreference被声讨的根源

 private void handleStopService(IBinder token) {
     QueuedWork.waitToFinish();      
 }
 public void handlePauseActivity(){
      QueuedWork.waitToFinish(); 
 }
 public void handleStopActivity(){
    QueuedWork.waitToFinish(); 
 }
public void handleServiceArgs(){
   QueuedWork.waitToFinish(); 
}

ActivityThread的以上方法里会调用 QueuedWork.waitToFinish(); 该代码会堵塞主线程执行等待SP的写入操作。这也是SP造成ANR的根源。

稍微展开点

   public static void waitToFinish() {
        while (true) {
                Runnable finisher;
                synchronized (sLock) {
                    finisher = sFinishers.poll();
                }
                if (finisher == null) {
                    break;
                }
                finisher.run();
            }
        } 
    }

waitToFinish()方法里有这样一段代码,sFinishers是一个List里面是存放的SP写入操作,会在SP执行commit和apply的时候放入进来。字节跳动团队就是在此处hook了使其poll()方法永远放回空,来杜绝此处产生的ANR。

7 、结

通过阅读ActivityThread的源码我们能在其中获取很多有用的知识。系统进程和应用进程通信的桥梁,Activity真正渲染的起始点,ContentProvider能实现SDK自动初始化的原理等都在ActivityThread看到他们的影子。

总结

找工作是个很辛苦的事情,而且一般周期都比较长,有时候既看个人技术,也看运气。第一次找工作,最后的结果虽然不尽如人意,不过收获远比offer大。接下来就是针对自己的不足,好好努力了。

最后为了节约大家的时间,我把我学习所用的资料和面试遇到的问题和答案都整理成了PDF文档

喜欢文章的话请关注、点赞、转发 谢谢!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

难做到真正的技术提升。**

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值