前言

现在大多数的App都会在重构的时候想到组件化或者说模块化,方便App解耦和优化。在我的理解里面组件化即将每个功能相同的模块一个个的装起来,然后以library的形式供我们的主app模块调用,而在主app模块中不会去进行任何的业务逻辑,只管打包好了,而除了主app模块,其他模块各回各家,各找各妈,干自己的业务逻辑去,简单的说组件化就是让library和application之间可以互相切换,libray可以作为单独的App运行也可以作为依赖库给主app调用;这种构建思想提升开发效率,减低代码的维护成本,减少代码的耦合度,让他人简单易懂。

组件化流程

Android系统组件化 android组件化实现_ide


模块虽然都独立出来了,但是如果每个模块都有想要调用其他模块的想法,那该怎么做呢?所以就要通过如上图所示中的Router这个中间人来替他们拉红线了?。

组件化Demo

说了这么多,开始写下demo

创建module

1.右击项目,点击Module

Android系统组件化 android组件化实现_java_02


2.如果是功能模块,要选择下图的红框选,其实也可以不选吧,如果仅仅是想作为libray的话

Android系统组件化 android组件化实现_android_03


3.这边要注意的是名字要有标准性的,就不要嫌麻烦取一样的名字了

Android系统组件化 android组件化实现_ide_04


Android系统组件化 android组件化实现_ide_05


4.统一每一个模块的SDK等版本,和设置模块是库还是app,在总项目的gradle.properties下设置

Android系统组件化 android组件化实现_android_06


5.记得导入依赖

Android系统组件化 android组件化实现_Android系统组件化_07


Android系统组件化 android组件化实现_android_08


导入自己创建的模块即可

6.每个模块下的build.gradle下配置如下内容

Android系统组件化 android组件化实现_java_09


Android系统组件化 android组件化实现_android_10


7.清单文件也需要判断

Android系统组件化 android组件化实现_android_11


8.创建中间人

ARouter.java该类进行其他模块的跳转通信

package com.hwt.arouter;

import android.app.Activity;
import android.app.Application;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Bundle;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import dalvik.system.DexFile;

/**
 * author:arrowHwt
 * Date:2019/7/14
 * Time:20:16
 */
public class ARouter {
    private static ARouter instance = new ARouter();

    //装载Activity的容器
    private Map<String,Class<? extends Activity>> activityList;

    private Context context;

    private ARouter(){
        activityList = new HashMap<>();
    }

    public static ARouter getInstance(){
        return instance;
    }

    public void init(Application application){
        this.context = application.getApplicationContext();
        List<String> classNames = getClassName("com.hwt.util");
        for (String className: classNames) {
            try {
                Class<?> aClass = Class.forName(className);
                //判断是否是IRouter的实现类
                if (IRouter.class.isAssignableFrom(aClass)){
                    IRouter iRouter = (IRouter) aClass.newInstance();
                    iRouter.putActivity();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


    public void putActivity(String path,Class<? extends Activity> clazz){
        if (path != null && clazz != null){
            activityList.put(path,clazz);
        }
    }

    public void jumpActivity(String path, Bundle bundle){
        //Activity的class对象
        Class<? extends Activity> aClass = activityList.get(path);
        if (aClass == null){
            return;
        }
        Intent intent = new Intent().setClass(context,aClass);

        if (bundle != null){
            intent.putExtra("bundle",bundle);
        }
        context.startActivity(intent);
    }

    /**
     * 通过包名拿到Class
     * @param packageName
     * @return
     */
    private List<String> getClassName(String packageName) {
        List<String> classList = new ArrayList<>();
        String path = null;
        try {
            path = context.getPackageManager().getApplicationInfo(context.getPackageName(),0).sourceDir;
            DexFile dexFile = new DexFile(path);
            Enumeration entries = dexFile.entries();
            while (entries.hasMoreElements()){
                String name = (String) entries.nextElement();
                if (name.contains(packageName)){
                    classList.add(name);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return classList;
    }

}

Android系统组件化 android组件化实现_Android系统组件化_12


9.通过注解,注解处理器(选择JavaLibrart,因为注解和注解处理器是java的)进行获取每个模块的类名,从而通过反射机制拿到每个模块中需要通信的类的所有信息

Android系统组件化 android组件化实现_Android系统组件化_13


10.添加注解依赖与步骤5一样,导入要用到该注解和注解处理器的模块中

注意:依赖注解处理器需要像下图一样使用annotationProcessor导入

Android系统组件化 android组件化实现_Android系统组件化_14


11.自定义自己的注解

Android系统组件化 android组件化实现_android_15


12.编写注解处理器

注解处理器的作用是自动生成类,以下是自动生成以时间为名字的跳转Activity的工具类

AnnotationComplier.java

package com.hwt.annotation_complier;

import com.google.auto.service.AutoService;
import com.hwt.annotation.BindPath;

import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Filer;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.tools.JavaFileObject;

/**
 * author:arrowHwt
 * Date:2019/7/14
 * Time:21:06
 * 注解处理器
 */
@AutoService(Processor.class)  //注册注解处理器
public class AnnotationComplier extends AbstractProcessor {
    //生成文件对象
    Filer filer;

    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {
        super.init(processingEnv);
        filer = processingEnv.getFiler();
    }

    /**
     * 声明注解处理器要处理哪些注解
     *
     * @return
     */
    @Override
    public Set<String> getSupportedAnnotationTypes() {
        Set<String> types = new HashSet<>();
        types.add(BindPath.class.getCanonicalName());
        return types;
    }

    /**
     * 声明注解处理支持的Java sdk的版本
     *
     * @return
     */
    @Override
    public SourceVersion getSupportedSourceVersion() {
        return processingEnv.getSourceVersion();
    }

    /**
     * 注解处理器的核心方法
     *
     * @param annotations
     * @param roundEnv
     * @return
     */
    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        //通过这个API就能拿到所有模块中所有用到BindPath注解的节点
        Set<? extends Element> elementsAnnotatedWith = roundEnv.getElementsAnnotatedWith(BindPath.class);
        //初始化数据
        Map<String, String> map = new HashMap<>();
        for (Element e : elementsAnnotatedWith) {
            TypeElement typeElement = (TypeElement) e;
            String key = typeElement.getAnnotation(BindPath.class).value();
            String value = typeElement.getQualifiedName().toString();
            map.put(key,value);
        }
        //开始写文件
        if (map.size() > 0){
            Writer writer = null;
            //创建类名
            String utilName = "ActivityUtil" + System.currentTimeMillis();
            try {
                JavaFileObject sourceFile = filer.createSourceFile("com.hwt.util."+utilName);
                writer = sourceFile.openWriter();
                writer.write("package com.hwt.util;\n" +
                        "\n" +
                        "import android.app.Activity;\n" +
                        "\n" +
                        "import com.hwt.arouter.ARouter;\n" +
                        "import com.hwt.arouter.IRouter;\n" +
                        "\n" +
                        "/**\n" +
                        " * author:arrowHwt\n" +
                        " * Date:2019/7/14\n" +
                        " * Time:20:35\n" +
                        " */\n" +
                        "public class "+ utilName+" implements IRouter {\n" +
                        "    @Override\n" +
                        "    public void putActivity() {");
                Iterator<String> iterator = map.keySet().iterator();
                while (iterator.hasNext()){
                    String key = iterator.next();
                    String value = map.get(key);

                    writer.write("ARouter.getInstance().putActivity(\""+key+"\","+
                            value+".class);\n");
                    writer.write("}\n}");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                if (writer != null){
                    try {
                        writer.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return false;
    }
}

13.最后在想要跳转的地方加入BindPath注解,然后再调用ARouter中的jumpActivity进行跳转

Android系统组件化 android组件化实现_android_16

package com.hwt.login;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

import com.hwt.annotation.BindPath;
import com.hwt.arouter.ARouter;

@BindPath("login/login")
public class LoginActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
    }

    public void jumpActivity(View view) {
        ARouter.getInstance().jumpActivity("member/member",null);
    }
}