什么是组件化(通俗易懂)
通俗易懂来讲就是,拆成多个module开发就是组件化。
app的部分功能模块在打包时并不以传统⽅式打包进apk⽂件中,⽽是以另⼀种形式⼆次封装进apk内部,或者放在⽹络上适时下载,在需要的时候动态对这些功能模块进⾏加载,称之为插件化。这些单独⼆次封装的功能模块apk,就称作插件,初始安装的apk称作宿主。插件化是组件化的更进⼀步推进。
插件化基础之反射:
反射的写法
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();
}
反射的⽬的
java既然提供了可⻅性关键字public、private等等,⽤来限制代码之间的可⻅性,为什么⼜要提供反射功能?可⻅性特性的⽀持不是为了代码不被坏⼈使⽤,⽽是为了程序开发的简洁性。安全性的话,可⻅性的⽀持提供的是safety 的安全,⽽不是security的安全。即,可⻅性的⽀持让程序更不容易写出bug,⽽不是更不容易被⼈⼊侵。反射的⽀持可以让开发者在可⻅性的例外场景中,可以突破可⻅性限制来调⽤⾃⼰需要的api。这是基于对开发者在使⽤反射时已经⾜够了解和谨慎的假设的。所以,可⻅性的⽀持不是为了防御外来者⼊侵,因此反射功能的⽀持并没有什么不合理。
关于dex:
- class:java编译后的⽂件,每个类对应⼀个class⽂件
- dex:dalvik executable把class打包在⼀起,⼀个dex可以包含多个class⽂件
- odex:optimized dex针对系统的优化,例如某个⽅法的调⽤指令,会把虚拟的调⽤转换为使⽤具体的index,这样在执⾏的时候就不⽤再查找了
- oat:optimized androidfile type。使⽤aot策略对dex预先编译(解释)成本地指令,这样再运⾏阶段就不需再经历⼀次解释过程,程序的运⾏可以更快
- 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⼯具来专⻔解决
- 懒加载来减少软件启动速度:有可能,实质上未必会快
- 减⼩安装包⼤⼩:可以
- 项⽬结构拆分,依赖完全隔离,⽅便多团队开发和测试,解决了组件化耦合度太⾼的问题:这个使⽤模块化就够了,况且模块化解耦不够的话,插件化也解决不了这个问题
- 动态部署:可以
- 热修复:可以
到此这篇关于android组件化、插件化详细讲解的文章就介绍到这了,更多相关android组件化,插件化内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!
