纯净、安全、绿色的下载网站

首页|软件分类|下载排行|最新软件|IT学院

当前位置:首页IT学院IT技术

Android ActivityThread APP启动过程 详解Android中的ActivityThread和APP启动过程

小河同学   2021-06-10 我要评论
想了解详解Android中的ActivityThread和APP启动过程的相关内容吗小河同学在本文为您仔细讲解Android ActivityThread APP启动过程的相关知识和一些Code实例欢迎阅读和指正我们先划重点:Android,ActivityThread,App,启动,Android,启动下面大家一起来学习吧

ActiviryThread

ActivityThread的初始化

ActivityThread即Android的主线程也就是UI线程ActivityThread的main方法是一个APP的真正入口MainLooper在它的main方法中被创建

//ActivityThread的main方法
public static void main(String[] args) {
    ...
    Looper.prepareMainLooper();
    ActivityThread thread = new ActivityThread();
    //在attach方法中会完成Application对象的初始化然后调用Application的onCreate()方法
    thread.attach(false);

    if (sMainThreadHandler == null) {
        sMainThreadHandler = thread.getHandler();
    }
    ...
    Looper.loop();
    throw new RuntimeException("Main thread loop unexpectedly exited");
}

接下来从主线程Looper的初始化和ApplicationThread及Activity的创建启动两方面通过源码了解学习下大致的流程

主线程Looper的初始化

Looper.prepareMainLooper();相关的代码如下

//主线程Looper的初始化
public static void prepareMainLooper() {
    prepare(false);
    synchronized (Looper.class) {
        if (sMainLooper != null) {
            throw new IllegalStateException("The main Looper has already been prepared.");
        }
        sMainLooper = myLooper();
    }
}

//普通线程Looper的初始化
public static void prepare() {
    prepare(true);
}

private static void prepare(boolean quitAllowed) {
    if (sThreadLocal.get() != null) {
        throw new RuntimeException("Only one Looper may be created per thread");
    }
    sThreadLocal.set(new Looper(quitAllowed));
}

看过Handler源码就知道主线程Looper的初始化和普通线程Looper的初始化很相似但还是有以下几个区别

1.普通线程的Prepare()默认quitAllowed参数为true表示允许退出而主线程也就是ActivityThread的Looper参数为false不允许退出这里的quitAllowed参数最终会传递给MessageQueue当调用MessageQueue的quit方法时会判断这个参数如果是主线程也就是quitAllowed参数为false时会抛出异常

//Looper的退时会判断quitAllowed
void quit(boolean safe) {
    if (!mQuitAllowed) {
        throw new IllegalStateException("Main thread not allowed to quit.");
    }
    synchronized (this) {
        ...
    }
}

2.我们注意到主线程Looper初始化之后赋值给了成员变量sMainLooper这个成员的作用就是向其他线程提供主线程的Looper对象这下我们就应该知道为什么Looper.getMainLooper()方法能获取主线程的Looper对象了

public static Looper getMainLooper() {
    synchronized (Looper.class) {
        return sMainLooper;
    }
}

主线程Handler的初始化

在ActivityThread的main方法中我们注意到一行代码:

ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
    sMainThreadHandler = thread.getHandler();
}

见名知意这是获取主线程的Handler那么主线程的Handler是在什么时候初始化的呢?

//与之相关的代码如下:
//ActivityThread的成员变量
final H mH = new H();

final Handler getHandler() {
    return mH;
}

从以上代码中可以看到主线程的Handler作为ActivityThread的成员变量是在ActivityThread的main方法被执行ActivityThread被创建时而初始化而接下来要说的ApplicationThread中的方法执行以及Activity的创建都依赖于主线程Handler至此我们也就明白了主线程(ActivityThread)的初始化是在它的main方法中主线程的Handler以及MainLooper的初始化时机都是在ActivityThread创建的时候

ApplicationThread及Activity的创建和启动

以上的代码和流程就是对 MainLooper 和 ActivityThread 的初始化我们接下来看一下 ActivityThread 的初始化及其对应的 attach 方法在thread.attach方法中ActivityManagerService通过attachApplication方法将ApplicationThread对象绑定到ActivityManagerServiceApplicationThread是ActivityThread的私有内部类实现了IBinder接口用于ActivityThread和ActivityManagerService的所在进程间通信

//ActivityThread的attach方法:
private void attach(boolean system) {
    ...
    if (!system) {
        final IActivityManager mgr = ActivityManager.getService();
        try {
            mgr.attachApplication(mAppThread);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }else{
            ...
        }
    }
}

//ActivityManagerService中的方法:
public final void attachApplication(IApplicationThread thread) {
    synchronized (this) {
        int callingPid = Binder.getCallingPid();
        final long origId = Binder.clearCallingIdentity();
        attachApplicationLocked(thread, callingPid);
        Binder.restoreCallingIdentity(origId);
    }
}

这里的个人理解是:在每个ActivityThread(APP)被创建的时候都需要向ActivityManagerService绑定(或者说是向远程服务AMS注册自己)用于AMS管理ActivityThread中的所有四大组件的生命周期

上述AMS的代码中attachApplicationLocked方法比较复杂主要功能有两个详见注释这里忽略了很多代码细节具体的流程可以看源码

//AMS中的方法主要功能有以下两步
private final boolean attachApplicationLocked(IApplicationThread thread, int pid) {
    ...
    //主要用于创建Application用调用onCreate方法
    thread.bindApplication(...);
    ...
    //主要用于创建Activity
    if (mStackSupervisor.attachApplicationLocked(app)) {
        ...
    }
}

1.thread.bindApplication:主要用于创建Application这里的thread对象是ApplicationThread在AMS中的代理对象所以这里的bindApplication方法最终会调用ApplicationThread.bindApplication()方法该方法会向ActivityThread的消息对应发送BIND_APPLICATION的消息消息的处理最终会调用Application.onCreate()方法这也说明Application.onCreate()方法的执行时机比任何Activity.onCreate()方法都早

//ActivityThread中的bindApplication方法
public final void bindApplication(...) {
    ...
    // 该消息的处理会调用handleBindApplication方法
    sendMessage(H.BIND_APPLICATION, data);
}
//ActivityThread中的handleBindApplication方法
private void handleBindApplication(AppBindData data) {
    ...
    try {
        Application app = data.info.makeApplication(data.restrictedBackupMode, null);
        mInitialApplication = app;
        ...
        try {
            mInstrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {
        }
    } finally {
    }
}
    
//LoadedApk中的方法用于创建Application
public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) {
    //如果存在Application的实例则直接返回这也说明Application是个单例
    if (mApplication != null) {
        return mApplication;
    }

    Application app = null;
    //...这里通过反射初始化Application

    if (instrumentation != null) {
        try {
            //调用Application的onCreate方法
            instrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {
        }
    }
    return app;
}

2.mStackSupervisor.attachApplicationLocked(app):用于创建ActivitymStackSupervisor是AMS的成员变量为Activity堆栈管理辅助类实例该方法最终会调用ApplicationThread类的scheduleLaunchActivity方法该方法也是类似于第一步向ActivityThread的消息队列发送创建Activity的消息最终在ActivityThread中完成创建Activity的操作

boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
    ...
    if (realStartActivityLocked(hr, app, true, true)) {
        ...
    }          
    ...
}

final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
    boolean andResume, boolean checkConfig) throws RemoteException {
    ...
    try {
        //调用ApplicationThread的scheduleLaunchActivity用于启动一个Activity
        app.thread.scheduleLaunchActivity(...);
    } catch (RemoteException e) {

    }
}

ApplicationThread的scheduleLaunchActivity方法会向ActivityThread发送LAUNCH_ACTIVITY信息用于启动一个Activity该消息的处理会调用ActivityThread的handleLaunchActivity方法最终启动一个Activity


相关文章

猜您喜欢

  • hashMap死循环 hashMap扩容时应该注意这些死循环问题

    想了解hashMap扩容时应该注意这些死循环问题的相关内容吗攻城狮numberOne在本文为您仔细讲解hashMap死循环的相关知识和一些Code实例欢迎阅读和指正我们先划重点:hashMap死循环问题,hashMap扩容下面大家一起来学习吧..
  • PyQt5 文件打开保存 Python3中PyQt5简单实现文件打开及保存

    想了解Python3中PyQt5简单实现文件打开及保存的相关内容吗LOONGV在本文为您仔细讲解PyQt5 文件打开保存的相关知识和一些Code实例欢迎阅读和指正我们先划重点:PyQt5,文件打开保存下面大家一起来学习吧..

网友评论

Copyright 2020 www.fresh-weather.com 【世纪下载站】 版权所有 软件发布

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 点此查看联系方式