zoukankan      html  css  js  c++  java
  • activityThread之内容分析

    2.读Android源码-冷启动时的ActivityThread

    1.Android ActivityThread工作原理

    ======

    2.读Android源码-冷启动时的ActivityThread

    前言:
    应用冷启动时需要创建进程,开启主线程,实例化应用所需组件。
    读ActivityThread源码有助于我们了解这个过程中,客户端做的那些事。

    冷启动创建应用时,ActivityThread的主要方法:

    1. main()
      -- 1. 开启消息循环
      -- 2. 通知ActivityManagerService
      -- 3. 添加GCWatcher
    2. handleBindApplication()
      -- 1. 创建LoadedApk
      -- 2. 创建Instrumentation
      -- 3. 创建Application
      -- 4. 通过Instrumentation调用Application的onCreate()方法

    main()

    main方法是一个应用创建的入口,他主要做了3件事

    1. 开启消息循环

    调用Looper.prepareLoop() Looper.loop(),开启主线程的消息循环,以便于ApplicationThread调用ActivityThread中的生命周期方法。

    public static void main(String[] args) {
        ...
        Looper.prepareMainLooper();
    
        ActivityThread thread = new ActivityThread();
        thread.attach(false);
    
        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }
        ...
        Looper.loop();
    }
    
    2. 通知ActivityManagerService

    调用ActivityThread.attach()方法,attach()方法在调用了attachApplication()将ApplicationThread这个Binder交给了ActivityManagerService,意味着ActivityManagerService可以通过ApplicationThread控制我们的应用,建立了服务器端对客户端的通信渠道。

    private void attach(boolean system){
        ...
        final IActivityManager mgr = ActivityManager.getService();
        try {
            mgr.attachApplication(mAppThread);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
        ...
    }
    

    SDK26以后,去除了Native和Proxy,而是直接从ActivityManager(ServiceManager)中获取ActivityManagerService的Binder对象进行通信

    3. 添加GCWatcher

    在attach()方法中,添加了监听dialvik内存使用情况得监听者GcWatcher,当内存使用超过总容量的3/4,则打印Log进行记录,并且调用ActivityManagerService的releaseSomeActivities()进行内存释放操作,以防止内存溢出导致应用崩溃。

    private void attach(boolean system){
        ...
        BinderInternal.addGcWatcher(new Runnable() {
            @Override public void run() {
                if (!mSomeActivitiesChanged) {
                    return;
                }
                Runtime runtime = Runtime.getRuntime();
                long dalvikMax = runtime.maxMemory();
                long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
                if (dalvikUsed > ((3*dalvikMax)/4)) {
                    if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)
                            + " total=" + (runtime.totalMemory()/1024)
                            + " used=" + (dalvikUsed/1024));
                    mSomeActivitiesChanged = false;
                    try {
                        mgr.releaseSomeActivities(mAppThread);
                    } catch (RemoteException e) {
                        throw e.rethrowFromSystemServer();
                    }
                }
            }
        });
        ...
    }
    

    handleBindApplication()

    ActivityManagerService=AMS
    handleBindApplication的被调用时机是:

    1. 通过上面AMS.attachApplication()后,AMS获得了控制应用的Binder对象ApplicationThread。
    2. AMS进行了一系列操作后(这里先省略),调用了ApplicationThread的bindApplication()
    3. bindApplication中通过消息机制,sendMessage到ActivityThread,调用了ActivityThread的handleBindApplication()

    handleBindApplication是创建用于所需组件的入口,他主要做了4件事:

    1. 创建LoadedApk

    LoadedApk对象包含应用的所有信息

    private void handleBindApplication(AppBindData data){
        ...
        final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
                        appContext.getClassLoader(), false, true, false);
        ...
    }
    
    2. 创建Instrumentation

    Instrumentation是应用组件的管家,组件的生命周期方法都需要通过它来调用,是客户端与服务器端通信的最后一步。

    private void handleBindApplication(AppBindData data){
        ...
        final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
        try {
            final ClassLoader cl = instrContext.getClassLoader();
            mInstrumentation = (Instrumentation)
                cl.loadClass(data.instrumentationName.getClassName()).newInstance();
        } catch (Exception e) {
            throw new RuntimeException(
                "Unable to instantiate instrumentation "
                + data.instrumentationName + ": " + e.toString(), e);
        }
        ...
    }
    
    3. 创建Application

    调用了LoadedApk.makeApplication()进行Application的创建

    private void handleBindApplication(AppBindData data){
        ...
        app = data.info.makeApplication(data.restrictedBackupMode, null);
        ...
    }
    
    • 先通过ContextImpl.createAppContext()获得Application的Context
    • 再通过Instrumentation.newApplication(),用ClassLoder创建Applicaition
    • 创建后Applicaition调用自身的attach(Context)方法,将Context与Applicaition绑定,完成创建
    LoadedApk.class
    public Application makeApplication(boolean forceDefaultAppClass,
                Instrumentation instrumentation) {
        ...
        Application app = null;
        ...
        ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
        app = mActivityThread.mInstrumentation.newApplication(
                cl, appClass, appContext);
        ...
        return app;
    }
    
    4. 通过Instrumentation调用Application的onCreate()方法
    private void handleBindApplication(AppBindData data){
        ...
        mInstrumentation.callApplicationOnCreate(app);
        ...
    }
    

    更新中...


     1.Android ActivityThread工作原理
     

    导读

    通过前面的学习(复习)我们知道ActivityThread其实不是一个Thread,而是一个final类型的Java类,并且拥有main(String[] args) 方法。Android原生以Java语言为基础,Java的JVM启动的入口就是main(String[] args)。

        public static void main(String[] args) {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
    
            // Install selective syscall interception
            AndroidOs.install();
    
            // CloseGuard defaults to true and can be quite spammy.  We
            // disable it here, but selectively enable it later (via
            // StrictMode) on debug builds, but using DropBox, not logs.
            CloseGuard.setEnabled(false);
    
            Environment.initForCurrentUser();
    
            // Make sure TrustedCertificateStore looks in the right place for CA certificates
            final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
            TrustedCertificateStore.setDefaultUserDirectory(configDir);
    
            Process.setArgV0("<pre-initialized>");
    
            Looper.prepareMainLooper();
    
            // Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.
            // It will be in the format "seq=114"
            long startSeq = 0;
            if (args != null) {
                for (int i = args.length - 1; i >= 0; --i) {
                    if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
                        startSeq = Long.parseLong(
                                args[i].substring(PROC_START_SEQ_IDENT.length()));
                    }
                }
            }
            ActivityThread thread = new ActivityThread();
            thread.attach(false, startSeq);
    
            if (sMainThreadHandler == null) {
                sMainThreadHandler = thread.getHandler();
            }
    
            if (false) {
                Looper.myLooper().setMessageLogging(new
                        LogPrinter(Log.DEBUG, "ActivityThread"));
            }
    
            // End of event ActivityThreadMain.
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            Looper.loop();
    
            throw new RuntimeException("Main thread loop unexpectedly exited");
        }
    

    以上为main方法中的全部代码,我们关注以下几点:

    • Looper.prepareMainLooper();
    • Looper.loop();
    • thread.attach(false, startSeq);
    • thread.getHandler();

    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();
            }
        }
        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));
        }
        public static @Nullable Looper myLooper() {
            return sThreadLocal.get();
        }
    

    可以看到new Looper的时候传了false

    Looper.loop();

    1.Looper就是字面意思(轮训器),在loop方法中无限循环的去MessageQueue(消息队列)中读取消息。

    1. MessageQueue则通过next方法无限循环的进行消息出队,无消息时则会进入睡眠

    执行thread.attach(false, startSeq);

    通过thread.attach(false, startSeq);把ActivityThread 和主线程进行绑定。

    执行thread.getHandler();

     
     
  • 相关阅读:
    Git push 出错 [The remote end hung up unexpectedly]
    [Git高级教程(二)] 远程仓库版本回退方法
    git分支与版本管理、版本回退、冲突解决记录
    上传本地代码到gitHub过程详解
    如何用git将项目代码上传到github
    Git pull 强制覆盖本地文件
    Git忽略规则.gitignore梳理
    composer本地安装文档
    服务器通过微信公众号Token验证测试的代码(Python版)
    转载自lanceyan: 一致性hash和solr千万级数据分布式搜索引擎中的应用
  • 原文地址:https://www.cnblogs.com/awkflf11/p/12662986.html
Copyright © 2011-2022 走看看