一 组件化和模块化的切换
1.新建一个组件化的module
2.新建文件config.gradle
3.在文件中输入控制组件化和模块化的参数
ext {
android = [
is_application: true
]
}
4.在项目的build.gradle中声明
这样声明了就是告诉项目在我们程序加载的时候去加载我们的config
5.然后在module中根据开关配置一下
代码
if (rootProject.ext.android.is_application) {
apply plugin: 'com.android.application'
} else {
apply plugin: 'com.android.library'
}
点击sync now 就可以了
二 Gradle统一版本号
1.在config.gradle命名公共配置
代码块
ext {
android = [
compileSdkVersion:32,
minSdkVersion: 21,
targetSdkVersion:32,
versionCode: 1,
versionName: "1.0",
is_application: true
]
}
2 然后在module中修改
代码块
android {
compileSdk rootProject.ext.android.compileSdkVersion
defaultConfig {
if (rootProject.ext.android.is_application) {
applicationId "com.example.merber"
}
minSdk rootProject.ext.android.minSdkVersion
targetSdk rootProject.ext.android.targetSdkVersion
versionCode rootProject.ext.android.versionCode
versionName rootProject.ext.android.versionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
三 AndroidManifest.xml文件的区分
因为application和library的AndroidManifest.xml文件是不同的,这个时候我们就需要区分了
我们再module模块中,添加一个manifest文件夹,并拷贝一份manifest文件进去
然后library的manifest文件是不需要intent的,这个时候就需要我们去掉intent以及Application里面的部分代码
代码
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.merber">
</manifest>
代码
sourceSets{
main {
if (rootProject.ext.android.is_application) {
manifest.srcFile 'src/main/AndroidManifest.xml'
} else {
manifest.srcFile 'src/main/manifest/AndroidManifest.xml'
}
}
}
四 library模块中不能有applicationId
这个异常是因为什么呢? 是因为我们的defaultConfig中设置了applicationId,但是library中是不需要的
怎么解决这个异常呢? 我们在设置applicationId的时候添加判断即可
五 组件之间的关联 1.建立annotation模块再建立文件
代码块
package com.example.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//编译时技术
@Target(ElementType.TYPE) //声明注解的作用域 放在什么上面
@Retention(RetentionPolicy.CLASS) //源码期 < 编译期 < 运行期 决定了注解的存在周期
public @interface BindPath {
//key
String value();
}
2 其他组件都引用annotation
3 需要调用的加 @BindPath("key/value") 这是将需要跳转的标记起来 下一步就是收集被标记的生成表格 apt技术
4.在每个组件中生成固定的包名
代码块
package com.example.router;
import com.example.arouter.ARouter;
import com.example.merber.MerberMainActivity;
public class MerberRouter {
public void putActivity(){
ARouter.getInstance().addActivity("merber/MerberMainActivity", MerberMainActivity.class);
}
}
5.建立总表new mode (arouter)
代码块
package com.example.arouter;
import android.app.Activity;
import android.content.Context;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ARouter {
//有一个容器 装载了所有模块中的Activity的类对象 路由表
private Map<String,Class<? extends Activity>> map;
private static ARouter aRouter = new ARouter();
private ARouter(){
map = new HashMap<>();
}
public static ARouter getInstance(){
return aRouter;
}
public void addActivity(String key,Class<? extends Activity> clazz){
if(key!=null && clazz!=null && !map.containsKey(key)){
map.put(key,clazz);
}
}
//上下文
private Context context;
}
建立接口
这样就完成了简单的模块化的东西了 但是使用还是不够方便 下面优化一下 让程序自己生成表
6 建立new mode(annotation_compiler)并添加注解处理器AnnotationCompiler
代码
import com.example.annotation.BindPath;
import com.google.auto.service.AutoService;
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;
//javac 就知道你
@AutoService(Processor.class)
public class AnnotationCompiler extends AbstractProcessor {
// 准备工作
//生成代码的工具
Filer filer;
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
filer = processingEnv.getFiler();
}
// 处理什么组件
@Override
public Set<String> getSupportedAnnotationTypes() {
Set<String> types = new HashSet<>();
types.add(BindPath.class.getCanonicalName());
return types;
}
//jdk版本
@Override
public SourceVersion getSupportedSourceVersion() {
return processingEnv.getSourceVersion();
}
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
// 1 elemtn
// MerberActivity PersonActivity 是 elements
Set<? extends Element> elements =roundEnvironment.getElementsAnnotatedWith(BindPath.class);
// 零部件 MerberActivity 长城汽车 的 所有零部件 PersonActivity 比亚迪 的 所有零部件
Map<String,String> map = new HashMap<>();
for (Element element : elements) {
//写文件
TypeElement typeElement = (TypeElement) element;
String activityName = typeElement.getQualifiedName().toString();
// key meber/PersonActivity.class
String key = typeElement.getAnnotation(BindPath.class).value();
map.put(key,activityName+".class");
}
if(map.size() >0){
//写文件
//生成工具类 然后写代码
//工具类的类名
String className = "ActivityUtil"+System.currentTimeMillis();
Writer writer = null;
try {
writer= filer.createSourceFile("com.example.util." + className).openWriter();
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("package com.example.util;\n");
stringBuffer.append("import com.example.arouter.ARouter;\n");
stringBuffer.append("import com.example.arouter.IRouter;\n");
stringBuffer.append("public class " + className + " implements IRouter {\n");
stringBuffer.append("@Override\n");
stringBuffer.append("public void putActivity() {\n");
Iterator<String> iterator = map.keySet().iterator();
while (iterator.hasNext()){
String key = iterator.next();
String activityName = map.get(key);
stringBuffer.append("ARouter.getInstance().addActivity(""+key+"","+activityName+");");
}
stringBuffer.append("\n}\n}");
writer.write(stringBuffer.toString());
} catch (IOException e) {
e.printStackTrace();
}finally {
if(writer!=null){
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
return false;
}
}
在builder中修改如下
plugins {
id 'java-library'
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
//3.4+<
annotationProcessor 'com.google.auto.service:auto-service:1.0-rc4'
compileOnly 'com.google.auto.service:auto-service:1.0-rc3'
//3.4-
// implementation 'com.google.auto.service:auto-service:1.0-rc1'
implementation project(path: ':annotation')
}
sourceCompatibility = "7"
targetCompatibility = "7"
组件依赖annotation_compiler 7.在组件的builder中修改
annotationProcessor project(path: ':annotation_compiler')
编译后会产生路由文件
8 我们做了组件的收集 现在要做到被调用(apt)
修改arouter
package com.example.arouter;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import dalvik.system.DexFile;
public class ARouter {
//有一个容器 装载了所有模块中的Activity的类对象 路由表
private Map<String,Class<? extends Activity>> map;
private static ARouter aRouter = new ARouter();
private ARouter(){
map = new HashMap<>();
}
public static ARouter getInstance(){
return aRouter;
}
public void addActivity(String key,Class<? extends Activity> clazz){
if(key!=null && clazz!=null && !map.containsKey(key)){
map.put(key,clazz);
}
}
//上下文
private Context context;
public void init(Context context){
this.context = context;
// com.example.util
//执行生成的工具类中的方法 将Activity的类对象加入到路由表中
List<String> classNames = getClassName("com.example.util");
for (String className : classNames) {
try {
Class<?> utilClass = Class.forName(className);
if(IRouter.class.isAssignableFrom(utilClass)){
IRouter iRouter = (IRouter) utilClass.newInstance();
iRouter.putActivity();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void jumpActivity(String key, Bundle bundle){
Class<? extends Activity> aClass = map.get(key);
if(aClass == null){
return;
}
Intent intent = new Intent(context,aClass);
if(bundle!=null){
intent.putExtras(bundle);
}
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
/**
* 通过包名获取这个包下面的所有的类名
* @param packageName
* @return
*/
private List<String> getClassName(String packageName) {
//创建一个class对象的集合
List<String> classList = new ArrayList<>();
try {
//把当前应有的apk存储路径给dexFile
DexFile df = new DexFile(context.getPackageCodePath());
// 不会发生类加载 性能 5000次 性能
Enumeration<String> entries = df.entries();
while (entries.hasMoreElements()) {
String className = (String) entries.nextElement();
if (className.contains(packageName)) {
classList.add(className);
}
}
} catch (IOException e) {
e.printStackTrace();
}
return classList;
}
}
在app中建立新的文件BaseApplication
代码
import android.app.Application;
import com.example.arouter.ARouter;
public class BaseApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
ARouter.getInstance().init(this);
}
}
在AndroidManifest中修改
android:name=".BaseApplication"
好了 组件化功能已经做完了,接下来在app调用merber 在app的mainActivity中调用
代码
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import com.example.arouter.ARouter;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textView = findViewById(R.id.button1);
textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
ARouter.getInstance().jumpActivity("merber/MerberMainActivity",null);
}
});
}
}