IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android Application创建流程 -> 正文阅读

[移动开发]Android Application创建流程

首先ActivityThread中的main()方法先执行了,

public static void main(String[] args){
    ......
    //创建Looper
    Looper.prepareMainLooper(); 
    ......
    //创建ActivityThread对象
    ActivityThread thread = new ActivityThread();
    //流程开始
    thread.attach(false);
    ......
    //最后启动消息循环。    
    Looper.loop();
}

可以看到,main方法中直接创建了ActivityThread对象,并且调用了ActivityThread的attach()方法,当前线程中调用了 Looper.prepareMainLooper();和Looper.loop()方法开启了主线程的消息机制。

看看ActivityThread#attach方法中做了什么事情。

public void attach(boolean system){
    //...省略非主流程代码。
    //获取ActivityMangerService的binder代理对象,这里返回的是ActivityMangerProxy对象,该对象内部持有ActivityMangerService的BinderProxy对象。
    final IActivityManager mgr = ActivityManagerNative.getDefault();  
    try {
     //执行ActivityMangerProxy的attachApplication()方法,内部会被系统回调到ActivityMangerService的attachApplication()中
        mgr.attachApplication(mAppThread);
    } catch (RemoteException ex) {
        throw ex.rethrowFromSystemServer();
    }
    //...省略非主流程代码。
}

我们先看看ActivityManagerNative.getDefault();是如何返回ActivityMangerProxy对象的:

//ActivityManger#getService(); 
public static IActivityManager getService() {
    return IActivityManagerSingleton.get();
}
*--------------------
//ActivityManger中的成员变量。
private static final Singleton<IActivityManager> IActivityManagerSingleton =
  new Singleton<IActivityManager>() {
     @Override
     protected IActivityManager create() {
      //从ServiceManger中获取Context.ACTIVITY_SERICE所对应的binder对象,获取的其实是ActivityMangerService,因为ActivityMangerService继承自ActivityMangerNative,ActivityMangerNative是继承自Bidner类的,所以ActivityMangerService本身就是Binder,并且在ActivityMangerService初始化的时候把自己注册到ServiceManger中,但是实际上获得的是由C层的BpBinder对象转换过来的BinderProxy对象。       
      final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
      //把BinderProxy对象转换成了ActivityManagerProxy对象
      final IActivityManager am = IActivityManager.Stub.asInterface(b);
      return am;
    }
};

根据Binder 机制,我们跨进程获取的Binder,在C层的时候,实际上获取的是Bpbiner对象,BpBinder进入java层会被转换成BinderProxy对象,所以从C层转换到Java层中,不管我们获取哪一个远程服务的binder,只要到来Java层,我们拿到的类型就算BinderProxy。因此,我们通常都做这么一个操作,调用“asInterface()”方法,把获取到的BinderProxy类型的对象,转换成具体的类型的Proxy对象。例如:要获取ActivityMangerService这个binder对象时,返回过来的是BinderProxy类型的Binder对象,之后将会被通过IAcitivytManager.Stub.asInterface(BinderProxy);方法转换成 ActivityManagerProxy对象。

好了,继续看方法。代码执行到:mgr.attachApplication(mAppThread); 而经过上面分析,我们知道执行的是ActivityManagerProxy的attachApplication()方法。我们先看看传入的参数是mAppThread。

final ApplicationThread mAppThread = new ApplicationThread();

查看代码发现 mAppThread是 ActivityThread类的成员变量,而且变量类型是AppLicationThread。我们看看该类的声明:

private class ApplicationThread extends ApplicationThreadNative {
    ......
}
----------------
public abstract class ApplicationThreadNative extends Binder implements IApplicationThread {
    ....
}

通过查看ApplicationThread的源码,我们能够清楚的看到ApplicationThread是继承自ApplicationThreadNative类,而ApplicationThreadNative类继承自Binder,因此,我们就能够知道ApplicationThread是一个binder类来的,用于进程间通信。

了解了ApplicationThread之后,回过来看这行代码:mgr.attachApplication(mAppThread); ,这时我们知道:通过ActivityMangerProxy调用attachApplication()方法,并传入一个ApplicationThread参数,ActivityMangerProxy的attachApplication()内部是会调用mRemote.transact(code,data,reply); code就是attchApplication方法所对应的int值,通过int值对方就能知道:“哦,你要执行attachApplication这个方法”,data是Pacal类型的对象,传入的所有参数都会被写入Pacal对象中进行传递,reply也是一个Pacal对象,对方的答复会被写入到这个Pacal对象中以供我们获取。这几个参数都会被Binder驱动传递给ActivityMangerService的onTransact();ActivityManagerService的onTransact方法基本没有处理,都是交给它的父类ActivityManagerNative的onTransact()方法处理的:

case ATTACH_APPLICATION_TRANSACTION: {
    data.enforceInterface(IActivityManager.descriptor);
    IApplicationThread app = ApplicationThreadNative.asInterface(
    data.readStrongBinder());
    if (app != null) {
         attachApplication(app);
     }
    reply.writeNoException();
    return true;
 }

可以看到,确实是根据int值执行对应的attachApplication();而 子类ActivityMangerService重写了该方法:

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

根据源码,可以发现attachApplication最主要执行的是attachApplicationLocked()方法,该方法的关键代码就是 通过 ApplicationThread的Binder代理类,执行了ApplicationThread#bindApplication();而ApplicationThread#bindApplication();的关键作用是 发送了一个handler消息(what值为H.BIND_APPLICATION的message消息)到主线程。

private class H extends Handler {
    public void handlerMessager(Message msg){
    //其他代码省略,就看这一个case中的代码。
      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);
      }
    }
}

最终执行handlerBindApplication();看看该方法做了什么事情。

private void handleBindApplication(AppBindData data) {
    //省略部分代码,只看关键代码
    //通过反射创建InStumentation。
    mInstrumentation = (Instrumentation)
        cl.loadClass(data.instrumentationName.getClassName())
        .newInstance();
    //初始化Instrumentation
    mInstrumentation.init(this, instrContext, appContext,new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher,data.instrumentationUiAutomationConnection);
    ......
    //执行Instrumentation的onCreate()方法;
    mInstrumentation.onCreate(data.instrumentationArgs);
  //通过LoadedApk的makeApplication()方法创建Application对象
    Application app = data.info.makeApplication(data.restrictedBackupMode, null);
    //保存Application对象
    mInitialApplication = app;
   //通过Instrumentation调用Application的onCreate()方法;
    mInstrumentation.callApplicationOnCreate(app);
}

看看LoadedApk的**makeApplication()**方法:

public Application makeApplication(boolean forceDefaultAppClass,
    Instrumentation instrumentation) {
   //判断是否初始化了Application是的话,直接返回
    if (mApplication != null) {
         return mApplication;
     }
   //获取Application的包名。那么肯定是需要反射的了
   String appClass = mApplicationInfo.className;
   java.lang.ClassLoader cl = getClassLoader();
   if (!mPackageName.equals("android")) initializeJavaContextClassLoader();
   //创建ApplicationContext;
   ContextImpl appContext = ContextImpl.createAppContext(mActivityThread,this);
 //通过Instrumentation创建一个Application
 app = mActivityThread.mInstrumentation.newApplication(cl,appClass,appContext);
}

然后再看看 Instrumentation是创建Application的大概流程:

//Instrumentation的newApplication方法有几个重载方法。
public Application newApplication(ClassLoader cl, String className, Context context) throws InstantiationException,IllegalAccessException,ClassNotFoundException {
   //根据传入的 Application的classname 获取Class对象
    return newApplication(cl.loadClass(className), context);
}
//Instrumentation的newApplication 
static public Application newApplication(Class<?> clazz, Context context) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
   //直接通过反射创建 Application对象
    Application app = (Application)clazz.newInstance();
    //并且设置context。这个Context就是前面Loaded.makeApplication()中创建的Context啊
    app.attach(context);
    return app;
}

到处。Application的创建完成。

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-07-04 19:58:19  更:2021-07-04 19:58:51 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/5 6:01:51-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码