组件化开发

传统的开发模式是将所有的东西都丢到APP模块里面,项目越做越大,适合组件化开发。

组件化分三层:

1. 业务逻辑层

2. 公共层(第三方库,框架)

3. 系统层

组件化开发的优势:

1.编译速度

每一个模块都是Application,只需要单独编译我的这个模块,别的模块不需要编译,节省时间

2.超级解耦

每个模块都是没有关联的,拆分成各个模块.模块之间是彼此之间是不关联的,彼此之间是没有任何耦合的

3.功能重用

不需要再copy过来,直接单独依赖这一模块就行

4.便于团队开发

节省沟通成本

组件化开发需要注意的点:

1.要注意包名和资源文件命名冲突问题

2.Gradle中的版本号的统一管理

3.组件在Application和Library之间可以随意的切换

4.AndroidManifest.xml的区分,Application和Library的AndroidManifest的内容是不一样的

app里面分为application类型插件和library类型插件。application插件生成apk包,library插件生成arr包

apply plugin: 'com.android.application'
apply plugin: 'com.android.library'

1.统一管理Gradle中的版本号,定义在gradle.properties文件里面,这个里面都是字符串类中

MIN_SDK_VERSION=18
TAR_SDK_VERSION=30
COMPILER_SDK_VERSION=30
BUILD_TOOL_VERSION=30.0.3
VERSION_CODE=1
VERSION_NAME=1.0
IS_APPLICATION=false

build.gradle中去使用,注意字符串类型转成Int类型

android {
    compileSdkVersion COMPILER_SDK_VERSION.toInteger()
    buildToolsVersion BUILD_TOOL_VERSION

    defaultConfig {
        applicationId "com.example.arouterdemo"
        minSdkVersion MIN_SDK_VERSION.toInteger()
        targetSdkVersion TAR_SDK_VERSION.toInteger()
        versionCode VERSION_CODE.toInteger()
        versionName VERSION_NAME

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

2.组件在Application和Library之间可以随意的切换

if (IS_APPLICATION.toBoolean()) {
    apply plugin: 'com.android.application'
} else {
    apply plugin: 'com.android.library'
}

直接通过一个全局变量IS_APPLICATION来进行随意的切换

3.AndroidManifest.xml的区分

Application和Library的AndroidManifest的内容是不一样的,需要生成一个manifest的文件夹再生成一个AndroidManifest.xml

Application的AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.member">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MemberActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Library的AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.member">

    <application>
        <activity android:name=".MemberActivity">

        </activity>
    </application>

</manifest>

 根据Application和Library来加载不同目录下的AndroidManifest.xml文件

   sourceSets {
        main {
            if (IS_APPLICATION.toBoolean()) {
                manifest.srcFile'src/main/AndroidManifest.xml'
            }else{
                manifest.srcFile'src/main/manifest/AndroidManifest.xml'
            }
        }
    }

只有Application才有applicationId ,Library是没有的

    defaultConfig {
        if (IS_APPLICATION.toBoolean()) {
            applicationId "com.example.member"
        }
        minSdkVersion MIN_SDK_VERSION.toInteger()
        targetSdkVersion TAR_SDK_VERSION.toInteger()
        versionCode VERSION_CODE.toInteger()
        versionName VERSION_NAME

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

APP模块依赖其他的Library不能依赖Application

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
    if (!IS_APPLICATION.toBoolean()) {
        implementation project(path: ':login')
        implementation project(path: ':member')
    }
}

login模块和member模块之间是没有任何的关联,组件化的优势是各个业务模块是完全解耦,没有关联,各个模块页面之间的跳转会比较困难.

组件化需要解决的问题-页面跳转

组件之间禁止相互依赖,如何在不同的组件之间进行页面跳转?

使用路由框架去解决页面跳转的问题

路由框架的原理:一系列特定url和特定Activity之间的的隐射集合

路由表里面的数据结构就是key和value的Map集合

应用启动的时候往路由表里面进行注册key和value。路由表是在内存里面,堆内存是共享的,都可以获取堆内存里面的数据。

首先创建一个中间人模块arouter

所有的业务模块(app、 login、 member)都依赖这个模块arouter

   implementation project(path: ':arouter')

思路:在arouter里面把整个应用的类对象都缓存在这个容器里面

产生一个单例Router,保证路由表的唯一

public class ARouter {
    private static final ARouter aRouter = new ARouter();

    //装载了所有Activity的类对象
    private Map<String, Class<? extends Activity>> maps;

    private Context context;

    public static ARouter getInstance() {
        return aRouter;
    }

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

    public void init(Context context) {
        this.context = context;
    }

    public void jumpActiviy(String key, Bundle bundle) {
        Class<? extends Activity> aClass = maps.get(key);
        if (aClass != null) {
            Intent intent = new Intent();
            intent.setClass(context, aClass);
            if (bundle != null) {
                intent.putExtras(bundle);
            }
            context.startActivity(intent);
        }

    }


}

 在login模块跳转member模块

public class LoginActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        jumpActivity();
    }

    public void jumpActivity() {
        ARouter.getInstance().jumpActiviy("member",null);
    }
}

那么怎么样将每个模块的Activity对象加入到map里面去?

来个接口,每个模块实现这个接口

public interface IRouter {
    void putActivity();
}

实现这个接口:

class ActivityUtils implements IRouter {
    @Override
    public void putActivity() {
        ARouter.getInstance().addActivity("login/login",LoginActivity.class);
    }
}

 增加addActivity()方法往map里面增加Activity

public class ARouter {
    private static final ARouter aRouter = new ARouter();

    //装载了所有Activity的类对象
    private Map<String, Class<? extends Activity>> maps;

    private Context context;

    public static ARouter getInstance() {
        return aRouter;
    }

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

    public void init(Context context) {
        this.context = context;
    }

   public void addActivity(String key, Class<? extends Activity> clazz) {
        if (key != null && clazz != null && !maps.containsKey(key)) {
            maps.put(key, clazz);
        }

    }

    public void jumpActiviy(String key, Bundle bundle) {
        Class<? extends Activity> aClass = maps.get(key);
        if (aClass != null) {
            Intent intent = new Intent();
            intent.setClass(context, aClass);
            if (bundle != null) {
                intent.putExtras(bundle);
            }
            context.startActivity(intent);
        }

    }


}

这样实现了,但是这样是比较麻烦的,假设有很多模块,每个模块都要写这个代码

class ActivityUtils implements IRouter {
    @Override
    public void putActivity() {
        ARouter.getInstance().addActivity("login/login",LoginActivity.class);
    }
}

使用编译时技术可以帮我们生成这个代码:使用注解和注解处理器来帮我们完成

注解和注解处理器都属于Java Library

所有的模块依赖注解和注解处理器

依赖方式

 implementation project(path: ':annotation')
 annotationProcessor project(path: ':annotation_compile')

定一个注解

@Target(ElementType.TYPE)//声明注解的作用域,就是放在什么上面
@Retention(RetentionPolicy.CLASS)//声明注解的生命周期,编译器
public @interface BindPath {
    String value();
}

使用

@BindPath("login/login")
public class LoginActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        jumpActivity();
    }

    public void jumpActivity() {
        ARouter.getInstance().jumpActiviy("member",null);
    }
}

注解处理器依赖的库

    compileOnly 'com.google.auto.service:auto-service:1.0-rc4'
    annotationProcessor 'com.google.auto.service:auto-service:1.0-rc4'
    implementation project(path: ':annotation')

不想去写工具类,让系统自动生成工具类,那么生成注解处理器帮我们去自动生成

anntation包实现下面的方法

@Target(ElementType.TYPE)//声明注解的作用域,就是放在什么上面
@Retention(RetentionPolicy.CLASS)//声明注解的生命周期,编译器
public @interface BindPath {
    String value();
}

 anntation_compile包实现下面的方法

@AutoService(Process.class) //注册注解处理器
class AnnotationCompiler extends AbstractProcessor {
    //生成文件的对象
    Filer filer;

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

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

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

    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
        //获取到当前模块用到的BindPath的节点
        //TypeElement类节点
        //ExecutableElement 方法节点
        //VariableElement 成员变量节点
        Set<? extends Element> elementsAnnotatedWith = roundEnvironment.getElementsAnnotatedWith(BindPath.class);
        Map<String,String> map =new HashMap<>();
        for (Element element:elementsAnnotatedWith){
            TypeElement typeElement = (TypeElement) element;
            //获取Activity上面的BindPath注解
            BindPath annotation = typeElement.getAnnotation(BindPath.class);
            String key = annotation.value();
            //获取包名加类名
            Name qualifiedName = typeElement.getQualifiedName();
            map.put(key,qualifiedName+".class");
        }

        if(map.size()>0){
            Writer writer = null;
            //生成文件的类名
            String activityName = "ActivityUtils"+System.currentTimeMillis();
            //生成一个文件
            try {
                JavaFileObject sourceFile = filer.createSourceFile("com.example.utils." + activityName);
                writer = sourceFile.openWriter();
                StringBuilder stringBuilder = new StringBuilder();
                stringBuilder.append("package com.example.utils;\n");
                stringBuilder.append("import com.example.arouter.ARouter;\n" +
                        "import com.example.arouter.IRouter;\n" +
                        "\n" +
                        "class ActivityUtils implements IRouter {\n" +
                        "    @Override\n" +
                        "    public void putActivity() {\n");

                Iterator<String> iterator = map.keySet().iterator();
                while (iterator.hasNext()){
                    String key = iterator.next();
                    String className = map.get(key);
                    //需要自己改下
                    stringBuilder.append("ARouter.getInstance().addActivity(\"login/login\",LoginActivity.class);\n");
                    stringBuilder.append("    }\n" +
                            "}");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }finally {
                if(writer!=null){
                    try {
                        writer.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return false;
    }
}

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
在Vue.js中,可以使用脚手架来支持组件开发。脚手架是一个用于快速生成项目结构和代码的工具。引用中提到的vde-cli脚手架就是一个例子。 使用Vue脚手架进行组件开发的步骤如下: 1. 首先,安装Vue脚手架(vde-cli)并创建一个新的Vue项目。可以通过以下命令进行安装: ``` npm install -g vde-cli ``` 然后,通过以下命令创建一个新的Vue项目: ``` vde create my-project ``` 2. 创建组件。在Vue项目中,可以将每个组件定义为一个单独的.vue文件。可以在项目的`src`目录中的`components`文件夹下创建组件文件。每个组件文件包含了组件的模板、样式和逻辑代码。 3. 在需要使用组件的地方,可以通过在Vue实例中引入组件,并在`components`选项中进行注册。例如,在父组件中使用子组件,可以在父组件的代码中添加以下内容: ``` <script> import MyComponent from '@/components/MyComponent.vue' export default { components: { MyComponent } } </script> ``` 4. 使用组件。在Vue模板中,可以通过组件的标签名来使用组件。例如,使用刚刚注册的`MyComponent`组件: ``` <template> <div> <my-component></my-component> </div> </template> ``` 这样,就可以在Vue项目中使用组件进行开发了。组件开发可以提高代码的复用性和维护性,使代码更加模块和可拓展。引用和都提到了组件开发的重要性和应用场景。 总结起来,组件开发是通过脚手架工具来创建项目结构,

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值