Android componentization, plug-in explanation

What is componentization (easy to understand)?

It is easy to understand that, splitting it into multiple modules for development is componentization.

What is plug-in (easy to understand)?

Some functional modules of the app are not packaged into the apk file in the traditional way, but are packaged into the apk twice in another form, or downloaded on the network in a timely manner, and dynamically updated when needed. These function modules are loaded, which is called plug-in. These separately encapsulated functional module apks are called plug-ins , and the initially installed apk is called the host . Plugin is a further advancement of componentization.

Plugin based reflection:

spelling of reflection

    try {
            Class utilClass = Class.forName("com.hencoder.demo.hidden.Util");
            Constructor utilConstructor = utilClass.getDeclaredConstructors()[0];
            utilConstructor.setAccessible(true);
            Object util = utilConstructor.newInstance();
            Method shoutMethod = utilClass.getDeclaredMethod("shout");
            shoutMethod.setAccessible(true);
            shoutMethod.invoke(util);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
复制代码

purpose of reflection

Since Java provides visibility keywords public, private, etc. to limit the visibility between codes, why do you need to provide reflection? The support of the visibility feature is not for the code not to be used by bad guys, but for the simplicity of program development. In terms of security, visibility support provides the security of Safety, not the security of Security. That is, visibility support makes programs less likely to write bugs, not less likely to be hacked. The support of reflection allows developers to break through the visibility restrictions to call the API they need in exception scenarios of visibility. This is based on the assumption that developers are sufficiently informed and cautious when using reflection . Therefore, the visibility support is not to defend against the invasion of outsiders, so the support of the reflection function is not unreasonable.

About DEX:

  • class: java compiled file, each class corresponds to a class file
  • dex: Dalvik EXecutable packages classes together, and a dex can contain multiple class files
  • odex: Optimized DEX is optimized for the system. For example, the call instruction of a method will convert the virtual call to use a specific index, so that there is no need to look up when executing it.
  • oat: Optimized Androidfile Type. Use the AOT strategy to precompile (interpret) dex into local instructions, so that there is no need to go through the interpretation process again in the re-running phase, and the program can run faster
  • AOT:Ahead-Of-Time compilation预先编译

插件化原理:动态加载

通过⾃定义ClassLoader来加载新的dex⽂件,从⽽让程序员原本没有的类可以被使⽤,这就是插件化的原理。 例如:把Utils拆到单独的项⽬,打包apk作为插件引⼊:

 File f = new File(getCacheDir() + "/demo-debug.apk");
        if (!f.exists()) {
            try { 
                InputStream is = getAssets().open("apk/demo-debug.apk");
                int size = is.available();
                byte[] buffer = new byte[size];
                is.read(buffer);
                is.close();
                FileOutputStream fos = new FileOutputStream(f);
                fos.write(buffer);
                fos.close();
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        
    DexClassLoader classLoader = new DexClassLoader(f.getPath(),
    getCodeCacheDir().getPath(), null, null);
      try {
            Class oldClass = classLoader.loadClass("com.hencoder.demo.hidden.Util");
            Constructor utilConstructor = oldClass.getDeclaredConstructors()[0];
            utilConstructor.setAccessible(true);
            Object util = utilConstructor.newInstance();
            Method shoutMethod = oldClass.getDeclaredMethod("shout");
            shoutMethod.setAccessible(true);
            shoutMethod.invoke(util);
            Class activityClass = classLoader.loadClass("com.hencoder.demo.MainActivity");
            startActivity(new Intent(this, activityClass));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
复制代码

问题⼀:未注册的组件(例如Activity)不能打开

  • 解决⽅式⼀:代理Activity
  • 解决⽅式⼆:欺骗系统
  • 解决⽅式三:重写gradle打包过程,合并AndroiManifest.xml

问题⼆:资源⽂件⽆法加载

解决⽅式:⾃定义AssetManager和Resources对象

   private AssetManager createAssetManager (String dexPath) {
        try {
            AssetManager assetManager = AssetManager.class.newInstance();
            Method addAssetPath = assetManager.getClass().getMethod("addAssetPath", String.class);
            addAssetPath.invoke(assetManager, dexPath);
            return assetManager;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
复制代码
private Resources createResources(AssetManager assetManager) {
        Resources superRes = mContext.getResources();
        Resources resources = new Resources(assetManager, superRes.getDisplayMetrics(), superRes.getConfiguration());
        return resources;
    }
复制代码

插件化有什么用?

  • 早期:解决dex 65535问题。⾕歌后来也出了multidex⼯具来专⻔解决
  • 懒加载来减少软件启动速度:有可能,实质上未必会快
  • 减⼩安装包⼤⼩:可以
  • 项⽬结构拆分,依赖完全隔离,⽅便多团队开发和测试,解决了组件化耦合度太⾼的问题:这个使⽤模块化就够了,况且模块化解耦不够的话,插件化也解决不了这个问题
  • 动态部署:可以
  • 热修复:可以

未完持续更新......

Guess you like

Origin juejin.im/post/7120149793489289247