Android插件化开发之解决OpenAtlas组件在宿主的注冊问题

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插件适配

最后,提供一个例子源代码

http://download.csdn.net/detail/sbsujjbcy/9031679

原文地址:https://www.cnblogs.com/mthoutai/p/7390983.html