Android插件化开发之解决OpenAtlas组件在宿主的注册问题
OpenAtlas有一个问题,就是四大组件必须在Manifest文件中进行注册,那么就必然带来一个问题,插件中的组件都要重复在宿主中注册。像Service,ContentProvider等组件目前没有什么好的解决方法,只能在宿主中注册。但是像Activity,显然是有解决方法的,就是使用Fragment代替Activity,Activity只是作为一个放Fragment的容器,那么不仅在插件中不用
OpenAtlas有一个问题,就是四大组件必须在Manifest文件中进行注册,那么就必然带来一个问题,插件中的组件都要重复在宿主中注册。像Service,ContentProvider等组件目前没有什么好的解决方法,只能在宿主中注册。但是像Activity,显然是有解决方法的,就是使用Fragment代替Activity,Activity只是作为一个放Fragment的容器,那么不仅在插件中不用再清单文件中注册,就连宿主的注册问题也一并解决了。那么,解决方案呢,没错,就是之前写的一篇博文Android使用Fragment打造万能页面切换框架。在阅读下文前,请务必先阅读该文章。
但是使用该页面切换框架也带来一个问题,就是该框架中是通过反射调用Fragment,但是在宿主中如果直接使用反射,会报java.lang.ClassNotFoundException的错误,我们必须使用OpenAtlas提供的插件的ClassLoader来加载,为了支持OpenAtlas,我对该框架进行了修改,使其支持OpenAtlas
在配置类CoreConfig中增加两个变量,控制是否启用OpenAtlas,以及用于设置和获得ClassLoader,并提供静态的getter和setter方法
/**
* Atlas支持 start
*/
private static boolean isOpenAtlas=false;
private static ClassLoader mBundleClassLoader =null;
public static boolean isOpenAtlas() {
return isOpenAtlas;
}
public static void setIsOpenAtlas(boolean isOpenAtlasFlag) {
isOpenAtlas = isOpenAtlasFlag;
}
public static ClassLoader getBundleClassLoader() {
return mBundleClassLoader;
}
public static void setBundleClassLoader(ClassLoader classLoader) {
mBundleClassLoader = classLoader;
}
/**
* Atlas支持 end
*/
修改原来的核心函数,判断CoreConfig中的布尔变量,是否启用了OpenAtlas,默认是不启用的。如果启用了,则通过getBundleClassLoader函数获得ClassLoader,但是前提是你调用了setBundleClassLoader函数设置了ClassLoader,返回的才不是空
/**
* Atlas的支持 start
*/
if (CoreConfig.isOpenAtlas()){
ClassLoader bundleClassLoader = CoreConfig.getBundleClassLoader();
if(bundleClassLoader==null){
Log.d(TAG, "OpenAtlas bundle ClassLoader is null!");
return null;
}
fragment = (BaseFragment) CoreConfig.getBundleClassLoader().loadClass(corePage.getClazz()).newInstance();
}else{
fragment = (BaseFragment) Class.forName(corePage.getClazz()).newInstance();
}
/**
* Atlas的支持 end
*/
之后在宿主中调用的时候,记得开启OpenAtlas的支持,并设置ClassLoader,而ClassLoader的获取是通过Atlas的成员函数getBundleClassLoader()来获取,该函数需要传递一个参数,该参数就是对应插件的包名,也就是之前生成的插件信息列表的json中的pkgName
之后的开发就是正常程序的开发了。但是注意一点,就是宿主的入口Activity必须继承页面切换框架中的BaseActivity,并且不需要调用setContentView进行页面设置,直接使用openPage函数打开Fragment即可,插件中的Fragment必须继承页面切换框架中的BaseFragment,并且记得在宿主Application中调用 CoreConfig.init(this);进行该框架的初始化。
然后在宿主中调用,记得设置ClassLoader和开启OpenAtlas的支持。Fragment的配置文件page.json 不需要拷到宿主中。
CoreConfig.setIsOpenAtlas(true);
ClassLoader bundleClassLoader = Atlas.getInstance().getBundleClassLoader("com.lizhangqu.fragment");
CoreConfig.setBundleClassLoader(bundleClassLoader);
openPage("test", null, CoreAnim.none);
而插件中,不应该将该框架打包进去,只是编译的时候提供,具体的适配工作见上一篇文章Android插件化开发之Atlas插件适配
最后,提供一个样例源码
更多推荐
所有评论(0)