Android-Init

Android 应用调度工具
授权协议 Apache
开发语言 Java
所属分类 手机/移动开发、 手机开发包
软件类型 开源软件
地区 国产
投 递 者 惠野
操作系统 Android
开源组织
适用人群 未知
 软件概览

Init 帮助 Android 应用调度复杂的任务流(如应用初始化流程),如下一节图示的那种任务流,处理类型、优先级、多进程(像是每个进程都会执行application的onCreate),任务依赖,提高应用启动效率。

尽管Init设计的初衷是为了应用(application)初始化,但并不局限于此,它可以于应用在任何复杂的初始化流程。

Init不依赖于任何第三方库,使用Java concurrent并部分依赖于Android SDK(Context, Log),所以理论上也可以在简单修改后直接用于Java工程。

How

初始化流程被抽象为flow、wave和task。

flow 是一个粗粒度概念,通常一个应用只有一个flow,但某些情况下我们可能拥有多个flow,像是patch flow,broadcast flow,fake UI flow等等,可以把它们都交给Init处理。

每个 wave 只有在上一wave的所有阻塞task完成后才能开始,而所有属于该wave的task会一起开始执行(除非被赋予了delay)。

至于task,在本库中属于原子性操作,他们可以被分为2大类型

  1. 阻塞task,即图中的蓝色任务。

  2. 异步task,又可以被分为

    • 完全异步或者横跨若干个wave后才需要阻塞,像图中的绿色task。

    • 异步链,像图中的红色task。

使用

dependencies {
    compile 'cn.zhaiyifan:init:1.0.1'
}
public class DemoApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        // Init需要应用context来获得进程相关信息
        Init.init(this);
        // 可以使用自定义的log离开输出Init的Log,logProxy需要实现cn.zhaiyifan.appinit.ILog接口
        // Init.init(this, logProxy)
        // 默认Task,延迟0,且阻塞下一波task的执行,参数字符串可以用来追踪任务执行状态
        Task task1 = new Task("task1") {
            @Override
            protected void start() {
                doSomeThing();
            }
            // 仅在返回true的时候才会在对应进程执行
            @Override
            public boolean runOnProcess(String processName) {
                return processName.equals("cn.zhaiyifan.demo");
            }
        };
        // 创建一个task,非阻塞,且延时300毫秒执行
        Task task2 = new Task("task2", false, 300) {
            @Override
            protected void start() {
                doSomeThing();
            }
        };
        // 类似地,创建更多task,如task3、task4等等
        // 创建一个有名flow
        Flow flow = new Flow("flow");
        // 往flow添加刚才创建的task, 第一个参数是wave序号,会从小到大执行每个wave的task
        flow.addTask(1, task1).addTask(1, task2).addTask(2, task3).addTask(2, task4);
        // 启动flow,开始初始化
        Init.start(flow);
    }

看一下log,可以发现原来一个串行执行需要2700毫秒的任务,在我们的安排下,现在只需要1307毫秒就可以结束。

10-04 18:53:54.789 646-666/cn.zhaiyifan.init I/Task: task2 runs 500
10-04 18:53:55.289 646-665/cn.zhaiyifan.init I/Task: task1 runs 1000
10-04 18:53:55.591 646-741/cn.zhaiyifan.init I/Task: task3 runs 300
10-04 18:53:55.592 646-646/cn.zhaiyifan.init I/Flow: flow runs 1307
10-04 18:53:55.990 646-740/cn.zhaiyifan.init I/Task: task4 runs 700
10-04 18:53:56.191 646-783/cn.zhaiyifan.init I/Task: task5 runs 200

Useful api:

// 设置线程池大小
Init.setThreadPoolSize(...)
// 取消一个已经开始的flow
Init.cancel(...)
// 获得flow状态
Init.getFlowStatus(...)
// 获得特定的task状态
flow.getTaskStatus(taskName)
// 设置超时限制
flow.setTimeout(5000)
等等

更多详情请见demo工程。

为什么需要 Init

想象一下我们是怎么去初始化一个大型应用像是支付宝、QQ、微信、空间等的,我们会面对像是下面这种代码:

public class XXXApplication {
    // for multi-dex apps
    @Override
    protected void attachBaseContext(Context base) {
        // log init
        ...
        // eventbus init...
        ...
        // global variables init
        ...
        // process related
        String processName = ...
        boolean isMainProcess = ...
        ProcessInit.attachBaseContext(this, processName, isMainProcess);
    }
    @Override
    protected void onCreate() {
        // process related
        String processName = ...
        boolean isMainProcess = ...
        // CrashHandler, SafeMode, plugin, image manager, database, download, update, etc init
        ProcessInit.onCreate(this, processName, isMainProcess);
    }
}
public class ProcessInit {
    ...
    public static void onCreate(Application application, boolean isMainProcess, String processName) {
        if (isMainProcess) {
        }
    } else if (processName.contains(PUSH_PROCESS_SUFFIX)) {
        ...
    } else if (processName.contains(WEB_PROCESS_SUFFIX)) {
        ...
    } else if (processName.contains(MUSIC_PROCESS_SUFFIX)) {
        ...
    } else {
        ...
    }
    ...
}

你看到了当一个应用越来越大以后初始化能是一件多么复杂的事情,有些操作必须在另一个之后,而又有一些可以并行执行,又有的操作又需要在一个异步操 作完成后才能执行......于是我们就得把每个独立的操作进行修改,有的改成异步,有的则阻塞在另一个操作后,使得代码杂乱且难以维护。

怎么可以使它变得简单呢?Init就是来帮助你做这个事的。

路线图

  • 1.0 10月 - 一个实现上述概念的可运行库 已完成

  • 1.1 2015年内 - 支持更复杂的初始化flow 进行中

  • 2.0 或许明年 - 从使用本库的代码可以直接逆向出初始化flow的图

  • 本文着重分析android-init启动流程 该进程为系统从内核空间启动的进程,是用户空间的鼻祖级进程。在此,谨分析两个层面: 一,kernel启动init 二,init启动流程 首先,kernel启动init 在bootloader的启动末段(经过了kernel解压缩和汇编执行启动阶段),会通过汇编直接调用init/main.c中start_kernel()接口,开始进入kernel部分执行,如

  • 概况: 启动init进程 运行init.rc 启动zygote服务 Zygote fork的第一个进程——SystemServer SystemServer启动系统服务 1. linux启动第一个应用程序init kernel\init\main.c static int __ref kernel_init(void *unused) { int ret; kernel_init_freeab

  • 本来好好的一个项目,都使用好久了的,结果在我加入讯飞语音识别功能,一切准备就绪,就差上机运行的时候,安装完apk之后突然闪退。。。一俩懵逼啊我,我确定我的代码都是非常完美的啊,并且该添加的权限啊,jar包啊啥的,该有的都有了啊,为啥还会闪退啊。 尤其是当我看到错误提示的时候也一脸懵逼 Rejecting re-init on previously-failed class java.lang.Cl

  • 问题:在手机上安装App时,无法启动App,Android Studio的logcat中显示“Rejecting re-init on previously-failed class”。 解决办法:关闭Android Studio中的Instant Run功能。File -> Setting -> Build,Execution,Deployment -> Instant Run,取消勾选。

  • 运行项目报错如下,提示找不到OnUnhandledKeyEventListener。 2019-05-16 10:56:58.801 6012-6012/? I/zygote64: Rejecting re-init on previously-failed class java.lang.Class<android.support.v4.view.ViewCompat$OnUnhandledKe

  • 1.首次启动init进程,并进入启动第一阶段 /system/bin/init → main.cpp:main()-→FirstStageMain() int main(int argc, char** argv) { #if __has_feature(address_sanitizer)     __asan_set_error_report_callback(AsanReportCallba

  • http://blog.chinaunix.net/uid-25314474-id-3204700.html 在android系统中,有一些初始化的配置文件,例如: /init.rc /default.prop /system/build.prop 文件里面里面配置了开机设置的系统属性值,   这些属性值,可以通过getprop获取,setprop设置, 它的格式如下: getprop [key]

  • init是一个进程,它是linux系统中用户空间的第一个进程,其进程PID是1,父进程为linux系统内核的0号进程。所以其被赋予很多极其重要的职责,linux内核初始化完成后就开始执行它。Android基于Linux内核,所以启动的第一个进程也是init 对于init进程的功能分为4部分: 分析和运行所有的init.rc文件; 生成设备驱动节点; (通过rc文件创建) 处理子进程的终止(sign

  • 一、init.rc文件结构 init.rc文件基本组成单位是section, section分为三种类型,分别由三个关键字(所谓关键字即每一行的第一列)来区分,这三个关键字是 on、service、import。 1、on类型的section表示一系列命令的组合 例如: on init export PATH /sbin:/system/sbin:/system/bin expor

  • aar 引入后运行时,提示Rejecting re-init on previously-failed class很有可能是aar编译时需要引入某库,而在依赖工程内不存在该库,并且编译通过,运行时报错,这时需要在依赖工程内引入该库,例如 你在编译导出aar 时使用了 compile 'me.weishu:epic:0.3.6' 那么在使用该aar的工程内 也需要引入该库,

  • 问题 log如下: 10-22 15:18:32.130 29298 29298 I art : Rejecting re-init on previously-failed class java.lang.Class<com.qiscus.sdk.chat.core.QiscusCore$$Lambda$4> 10-22 15:18:32.130 29298 29298 I art

  • 在http://blog.csdn.net/kc58236582/article/details/52247547这篇博客中,我们分析了init进程的流程,现在我们结合代码主要分析init.rc脚本的流程。   首先我们会加载原生的init.rc,然后我们自己的一些内容放在自己的init.rc中。然后会在原生的init.rc中import。 而原生会通过ro.hardware这个属性,来获取我们设

 相关资料
  • 应用调度指的是在 WSGI 层次合并运行多个 Flask 的应用的进程。您不能将 Flask 与更大的东西合并,但是可以和 WSGI 应用交叉。这甚至允许您将 Django 和 Flask 的应用运行在同一个解释器下。这么做的用处依赖于 这个应用内部是如何运行的。 与 模块方式 的区别在于,此时您运行的不 同 Flask 应用是相互之间完全独立的,他们运行在不同的配置,而且在 WSGI 层调度。

  • 本文向大家介绍Android Zipalign工具优化Android APK应用,包括了Android Zipalign工具优化Android APK应用的使用技巧和注意事项,需要的朋友参考一下        生成的Android应用APK文件最好进行优化,因为APK包的本质是一个zip压缩文档,经过优化能使包内未压缩的数据有序的排列,从而减少应用程序运行时的内存消耗。我们可以使用Zipalign

  • 应用亮度/对比度调整 使用“亮度/对比度”调整,可以对图像的色调范围进行简单的调整。将亮度滑块向右移动会增加色调值并扩展图像高光,而将亮度滑块向左移动会减少值并扩展阴影。对比度滑块可扩展或收缩图像中色调值的总体范围。 在正常模式中,“亮度/对比度”会与“色阶”和“曲线”调整一样,按比例(非线性)调整图像图层。当选定“使用旧版”时,“亮度/对比度”在调整亮度时只是简单地增大或减小所有像素值。由于这样

  • 我一直在尝试运行我的客户端/服务器android程序。但是每当我在android上运行客户端部分时,它都会出错不幸的是,您的应用程序已停止运行。我尝试过阅读logcat,但无法解决问题。下面是我的代码...我从3天开始一直在尝试。需要项目帮助 logcat公司 activity\u new\u main\u活动。xml manifest.xml 新建_main_活动。Java语言

  • 本文向大家介绍Android 调试工具用法详细介绍,包括了Android 调试工具用法详细介绍的使用技巧和注意事项,需要的朋友参考一下 本文主要为大家讲解多种Android调试工具的用法。        1. 查看当前堆栈        1)功能:在程序中加入代码,使可以在logcat中看到打印出的当前函数调用关系。        2)方法:        new Exception(“print

  • 目前我正在研究文本字段和默认/取消按钮的问题。在使用TestFX测试假定的修复时,我遇到了事件调度方面的差异(?)这使得测试在应用程序运行时失败。 下面是一个非常简化的版本: 只是一个简单的用户界面,由一个框中的文本字段组成,用于应用程序/测试 修复程序的关键部分是创建actionEvent,将textField同时作为源和目标(以防止在调度期间将事件复制到新实例中): 运行应用程序时,这似乎足以

  • 我在visual studio中创建了一个dll(我没有使用任何win\u API函数)。我想从我生成的android.apk文件中调用这个dlll,但在运行这个文件时,我遇到了这个错误。 "java.lang.无法从加载器加载Testdll1dalvik.system.PathClassLoader[DexPathList[[zip file"/data/app/], nativeLibrary

  • My AndroidManifest.xml 文件 我的Gradle 我尝试清理/重建 gradle 项目、重新启动 Android Studio、使缓存失效和 rebbot ADB 集成(工具 - 有什么想法吗? 附言:在此之前,我更改了应用程序包的名称 P、 Android Studio无法调试其他项目。