美文网首页Android开发知识小集Android收藏集Android专题
Android组件化-动态配置Application实践

Android组件化-动态配置Application实践

作者: xu_pan | 来源:发表于2019-03-04 22:37 被阅读176次

        在组件化开发的过程中,在不增加模块间耦合的情况下,如果某些功能模块需要进行初始化,如何进行操作呢?这里先说一下常规的配置思路,后面会在这种方式的基础上做进一步的优化。

    (1)在base模块中定义抽象类,类中涵盖了Application中的几个方法。

    public abstract class BaseAppLogic {
    
        protected Application mApplication;
    
        public BaseAppLogic(){
        }
    
        public void setApplication(Application application){
            this.mApplication = application;
        }
    
        public void onCreate(){}
    
        public void onTerminate(){}
    
        public void onLowMemory(){}
    
        public void onTrimMemory(int level){}
    
        public void onConfigurationChanged(Configuration newConfig){}
    }
    

    (2)在功能模块中创建一个"假的"Application继承该BaseAppLogic

    public class TestApplication extends BaseAppLogic {
        private static final String TAG = "TestApplication";
        @Override
        public void onCreate() {
            super.onCreate();
            Log.e(TAG,"test for application");
        }
    
        @Override
        public void onLowMemory() {
            super.onLowMemory();
        }
    
        @Override
        public void onTrimMemory(int level) {
            super.onTrimMemory(level);
        }
    
        @Override
        public void onTerminate() {
            super.onTerminate();
        }
    
        @Override
        public void onConfigurationChanged(Configuration newConfig) {
            super.onConfigurationChanged(newConfig);
        }
    }
    

    (3)将主模块中的Application与功能模块的"Application"进行绑定。

    public class MainApplication extends Application {
        private String[] appClazz = new String[]{"com.px.xxx.TestApplication"};
        private ArrayList<BaseAppLogic> applicationList = new ArrayList<>();
        @Override
        public void onCreate() {
            super.onCreate();
            initAppLogic();
        }
        
        private void initAppLogic(){
            for(String className : appClazz){
                try {
                    Class<?> clazz = Class.forName(className);
                    try {
                        BaseAppLogic appLogic = (BaseAppLogic) clazz.newInstance();
                        appLogic.onCreate();
                        applicationList.add(appLogic);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (InstantiationException e) {
                        e.printStackTrace();
                    }
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
        }
    
        @Override
        public void onTerminate() {
            super.onTerminate();
            for(BaseAppLogic appLogic:applicationList){
                appLogic.onTerminate();
            }
        }
    }
    

        至此,为了降低耦合,使用反射完成了组件化的Application的配置。(什么?你说使用反射影响性能?下一篇我们来探讨反射对性能的影响究竟有多大)。对于项目中功能组件较少,或者开发团队成员较少的情况,使用以上的方式就足够了。

        我们可以看到在(3)中,我们需要显示的在主模块中注册功能模块"Application"的类名,这样虽然我们实现了代码上的低耦合,却没有实现在开发过程中人员模块操作界限的分离。在实际的开发过程中,开发人员各自负责自己的模块,甚至有可能没有主模块的修改权限。为此我将上述方案推进了一步,使用编译时注解自动实现模块中"Application"信息的收集

    (1)定义注解。该注解用来标识上述功能模块中假的"Application"

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.CLASS)
    public @interface AppLogic {
        //为true时在Application的onCreate方法中最后执行
        boolean delay() default false;
        //优先级,值越大越先执行
        int priority() default 0;
    }
    

    (2)使用poet实现对该运行时注解的解释器,目的是将所有被注解的类的信息收集起来。

    @AutoService(Processor.class)
    @SupportedAnnotationTypes({"com.px.annotation.AppLogic"})
    @SupportedSourceVersion(SourceVersion.RELEASE_7)
    public class AppLogicProcessor extends AbstractProcessor {
    
        private Filer filer;
        private ArrayList<AppLogicInfo> mData = new ArrayList<>();
    
        @Override
        public synchronized void init(ProcessingEnvironment processingEnvironment) {
            super.init(processingEnvironment);
            filer = processingEnv.getFiler();
        }
    
        @Override
        public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
            collectInfo(roundEnvironment);
            writeToFile();
            return true;
        }
        
        //收集所有被注解的类的信息
        private void collectInfo(RoundEnvironment roundEnvironment){
            Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(AppLogic.class);
            for(Element element : elements){
                AppLogicInfo appLogicInfo = new AppLogicInfo();
                boolean delay = element.getAnnotation(AppLogic.class).delay();
                int priority = element.getAnnotation(AppLogic.class).priority();
    
                TypeElement typeElement = (TypeElement)element;
                String classFullName = typeElement.getQualifiedName().toString();
                appLogicInfo.setClassName(classFullName);
                appLogicInfo.setDelay(delay);
                appLogicInfo.setPriority(priority);
                mData.add(appLogicInfo);
            }
        }
        
        //将被注解的类的信息,写到一个类""Test$$AppLogic.java""中
        public void writeToFile() {
            try {
                String packageFullName = "com.px.applogicdem";
    
                ClassName ArrayList = ClassName.get("java.util","ArrayList");
    
                ClassName appLogicInfo = ClassName.get("com.px.api","AppLogicInfo");
                TypeName arrayListType = ParameterizedTypeName.get(ArrayList, appLogicInfo);
                FieldSpec arrayList = FieldSpec.builder(arrayListType,"testArrayList")
                        .addModifiers(Modifier.PUBLIC)
                        .initializer("new $T()",arrayListType)
                        .build();
    
                MethodSpec.Builder methodSpec2 = MethodSpec.constructorBuilder()
                        .addModifiers(Modifier.PUBLIC);
               for(int i= 0;i<mData.size();i++){
                   String temp = "temp"+i;
                    methodSpec2.addStatement("$T "+temp+" = new $T()",appLogicInfo ,appLogicInfo)
                            .addStatement(temp+".setClassName($S)",mData.get(i).getClassName())
                            .addStatement(temp+".setDelay("+mData.get(i).isDelay()+")")
                            .addStatement(temp+".setPriority("+mData.get(i).getPriority()+")")
                            .addStatement("testArrayList.add("+temp+")");
                }
                // 构建Class
                TypeSpec typeSpec = TypeSpec.classBuilder("Test" + "$$AppLogic")
                        .addModifiers(Modifier.PUBLIC)
                        .addMethod(methodSpec2.build())
                        .addField(arrayList)
                        .build();
                JavaFile javaFile = JavaFile.builder(packageFullName, typeSpec)
                        .build();
                // 生成class文件
                javaFile.writeTo(filer);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    

    (3)为功能模块中的Application添加注解

    @AppLogic
    public class TestApplication extends BaseAppLogic {
        private static final String TAG = "TestApplication";
        @Override
        public void onCreate() {
            super.onCreate();
            Log.e(TAG,"test for application");
        }
    
        @Override
        public void onLowMemory() {
            super.onLowMemory();
        }
    
        @Override
        public void onTrimMemory(int level) {
            super.onTrimMemory(level);
        }
    
        @Override
        public void onTerminate() {
            super.onTerminate();
        }
    
        @Override
        public void onConfigurationChanged(Configuration newConfig) {
            super.onConfigurationChanged(newConfig);
        }
    }
    

    (4)编译一下代码,检查下注解解释器是否为我们自动生成了类,poet生成的代码如下。

    public class Test$$AppLogic {
      public ArrayList<AppLogicInfo> testArrayList = new ArrayList<AppLogicInfo>();
    
      public Test$$AppLogic() {
        AppLogicInfo temp0 = new AppLogicInfo();
        temp0.setClassName("com.px.testlib.TestApplication");
        temp0.setDelay(false);
        temp0.setPriority(0);
        testArrayList.add(temp0);
      }
    }
    

    (5)有了第四步的自动生成的代码,我们就可以通过一个工具类将主模块中的Application与功能模块中的"Application"进行绑定了。

    public class AppLogicInject {
    
        private static ArrayList<AppLogicInfo> appLogicInfos;
        private static Application mApplication;
        private static ArrayList<BaseAppLogic> appLogicList = new ArrayList<>();
    
        public static void inject(Application application) {
            mApplication = application;
            String className = "com.px.applogicdem.Test$$AppLogic";
            try {
                Class clasz = Class.forName(className);
                Object object = clasz.newInstance();
                Field field = object.getClass().getField("testArrayList");
                appLogicInfos = (ArrayList<AppLogicInfo>) field.get(object);
                Collections.sort(appLogicInfos, new AppLogicInfo());
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            }
        }
        
        public static void onCreate() {
            if(appLogicInfos == null){
                return;
            }
            for (AppLogicInfo appLogicInfo : appLogicInfos) {
                if (appLogicInfo.isDelay()) {
                    continue;
                }
                createAppLogic(appLogicInfo);
            }
        }
    
        public static void onCreateDelay() {
            if(appLogicInfos == null){
                return;
            }
            for (AppLogicInfo appLogicInfo : appLogicInfos) {
                if (appLogicInfo.isDelay()) {
                    createAppLogic(appLogicInfo);
                }
            }
        }
    
        private static void createAppLogic(AppLogicInfo appLogicInfo) {
            try {
                Class<?> clazz = Class.forName(appLogicInfo.getClassName());
                BaseAppLogic appLogic = (BaseAppLogic) clazz.newInstance();
                appLogic.setApplication(mApplication);
                appLogic.onCreate();
                appLogicList.add(appLogic);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InstantiationException e) {
                e.printStackTrace();
            }
        }
    
        public static void onTerminate() {
            for (BaseAppLogic appLogic : appLogicList) {
                appLogic.onTerminate();
            }
        }
    
        public static void onLowMemory() {
            for (BaseAppLogic appLogic : appLogicList) {
                appLogic.onLowMemory();
            }
        }
    
        public static void onTrimMemory(int level) {
            for (BaseAppLogic appLogic : appLogicList) {
                appLogic.onTrimMemory(level);
            }
        }
    
        public static void onConfigurationChanged(Configuration newConfig) {
            for (BaseAppLogic appLogic : appLogicList) {
                appLogic.onConfigurationChanged(newConfig);
            }
        }
    
    }
    

    (6)Application中的代码如下

    public class MyApplication extends Application {
        @Override
        public void onCreate() {
            super.onCreate();
            AppLogicInject.inject(this);
            AppLogicInject.onCreate();
            //其他的初始化操作
            AppLogicInject.onCreateDelay();
        }
    
        @Override
        public void onTerminate() {
            super.onTerminate();
            AppLogicInject.onTerminate();
        }
    
        @Override
        public void onLowMemory() {
            super.onLowMemory();
            AppLogicInject.onLowMemory();
        }
    
        @Override
        public void onTrimMemory(int level) {
            super.onTrimMemory(level);
            AppLogicInject.onTrimMemory(level);
        }
    
        @Override
        public void onConfigurationChanged(Configuration newConfig) {
            super.onConfigurationChanged(newConfig);
            AppLogicInject.onConfigurationChanged(newConfig);
        }
    }
    

    Demo下载地址

    相关文章

      网友评论

        本文标题:Android组件化-动态配置Application实践

        本文链接:https://www.haomeiwen.com/subject/xkfluqtx.html