美文网首页android开发技巧
Android组件化开发的意义何在?

Android组件化开发的意义何在?

作者: 今日Android | 来源:发表于2020-10-30 18:30 被阅读0次

    安卓组件化开发的意义

    当项目比较大需要多人协同开发的时候,组件化开发可以使大家分模块开发,并且不会互相影响。并且可以单独调试,不受其他模块制约。

    项目结构解析

    创建一个主应用,两个子应用(既可以做应用,也可以作为主应用的依赖),一个base库实现主应用和子应用的通讯。创建后项目结构如下


    统一项目编译版本

    • gradle.properties文件设置统一版本
        # 统一编译版本等信息
        compile_Sdk_Version=28
        min_Sdk_Version=15
        target_Sdk_Version=28
    
    
    • 修改app、loginmodule、memodule、mudulelibrary的编译版本,以app为例
        apply plugin: 'com.android.application'
    
        android {
            compileSdkVersion compile_Sdk_Version.toInteger()
            defaultConfig {
                applicationId "com.syw.modulesdemo"
                minSdkVersion min_Sdk_Version.toInteger()
                targetSdkVersion target_Sdk_Version.toInteger()
                versionCode 1
                versionName "1.0"
                testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
            }
            buildTypes {
                release {
                    minifyEnabled false
                    proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
                }
            }
        }
    
    

    设置application和library切换开关

    • gradle.properties文件设置切换开关
        # application和library切换开关
        isLoginApplication=true
        isMeApplication=true
    
    
    • 主应用动态添加依赖
        //不要忘记toBoolean()
        if (!isLoginApplication.toBoolean()) {
            implementation project(':loginmodule')
        }
        if (!isMeApplication.toBoolean()) {
            implementation project(':memodule')
        }
        implementation project(':modulelibrary')
    
    
    • 子应用切换application和library、动态设置applicationId、动态设置AndroidManifest.xml、添加基础依赖。以login模块为例
        //1.动态设置application或library
        if (isLoginApplication.toBoolean()){
            apply plugin: 'com.android.application'
        }else{
            apply plugin: 'com.android.library'
        }
    
        android {
            compileSdkVersion compile_Sdk_Version.toInteger()
    
            defaultConfig {
                //2.library不存在applicationId
                if (isLoginApplication.toBoolean()){
                    applicationId "com.syw.loginmodule"
                }
                minSdkVersion min_Sdk_Version.toInteger()
                targetSdkVersion target_Sdk_Version.toInteger()
                versionCode 1
                versionName "1.0"
                testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
            }
    
            buildTypes {
                release {
                    minifyEnabled false
                    proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
                }
            }
    
        //    3.library状态下AndroidManifest.xml没有application信息,不设置启动activity
            sourceSets{
                main{
                    if (isLoginApplication.toBoolean()){
                        manifest.srcFile 'src/main/AndroidManifest.xml'
                    }else{
                        manifest.srcFile 'src/main/manifests/AndroidManifest.xml'
                    }
                }
            }
        }
    
        dependencies {
            implementation fileTree(include: ['*.jar'], dir: 'libs')
            implementation 'com.android.support:appcompat-v7:28.0.0'
            implementation 'com.android.support.constraint:constraint-layout:2.0.2'
            testImplementation 'junit:junit:4.12'
            androidTestImplementation 'com.android.support.test:runner:1.0.2'
            androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
            implementation project(':modulelibrary')
        }
    
    

    依赖库的manifest.xml

        <?xml version="1.0" encoding="utf-8"?>
        <manifest xmlns:android="http://schemas.android.com/apk/res/android"
            package="com.syw.loginmodule">
    
            <application>
                <activity android:name=".LoginActivity">
                </activity>
            </application>
    
        </manifest>
    
    

    基础库设置

    基础库设置接口,由子项目实现

    以login模块为例,编写ILoginService

        public interface ILoginService {
            void launch(Context context);
    
            Fragment getFragment(FragmentManager fragmentManager, int containerId, Bundle bundle);
        }
    
    

    编写接口管理类

    public class ServiceFactory {
        // 单例模式
        private static final ServiceFactory instance=new ServiceFactory();
        public ServiceFactory(){}
        public static ServiceFactory getInstance() {
            return instance;
        }
    
        private ILoginService iLoginService;
        private IMeService iMeService;
    
        public ILoginService getLoginService() {
            return iLoginService;
        }
    
        public void setLoginService(ILoginService iLoginService) {
            this.iLoginService = iLoginService;
        }
    
        public IMeService getMeService() {
            return iMeService;
        }
    
        public void setMeService(IMeService iMeService) {
            this.iMeService = iMeService;
        }
    }
    
    

    子项目完成具体实现

    public class LoginBridge implements ILoginService {
        @Override
        public void launch(Context context) {
            Intent intent = new Intent(context, LoginActivity.class);
            context.startActivity(intent);
        }
    
        @Override
        public Fragment getFragment(FragmentManager fragmentManager, int containerId, Bundle bundle) {
            LoginFragment loginFragment=new LoginFragment();
            loginFragment.setFragmentData(bundle);
            fragmentManager.beginTransaction().add(containerId,loginFragment).commit();
            return loginFragment;
        }
    }
    
    

    跳转方法的调用

    跳转的具体实现已经完成,现在的问题是怎么调用,我们想要实现的是在MainActivity中通过如下代码调用

        ServiceFactory.getInstance().getLoginService().launch(MainActivity.this);
    
    

    那么现在的问题是,什么时候将LoginService设置到ServiceFactory,刚开始的时候还在想,既然已经依赖了loginmodule,为啥不直接跳转。仔细想想,这就违背了组件化的本意了,我们应该减少子项目和主项目之间的耦合,通过中间库的方式。
    为了调用getLoginService,我们首先需要setLoginService,将实现类设置到ServiceFactory。于是就有了下面的方法

    在子项目中创建一个方法,在主项目初始化的时候,通过主项目调用,子项目将实现类设置给ServiceManager
    • 我们首先需要在基础库创建一个接口,通过主项目调用,实现全部子应用设置Service
        public interface Appcompat {
            void initializa();
        }
    
    
    • 我们首先创建一个类,实现该接口,设置LoginService
        public class LoginApplication extends Application implements Appcompat {
            @Override
            public void initializa() {
                ServiceManager.getInstance().setLoginService(new LoginBridge());
            }
        }
    
    
    • 我们创建一个类,管理所有子项目设置Service的类。主项目通过反射的方法调用,实现全部子应用设置Service
        public class AppConfig {
            public static final String[] COMPONENT={
              "com.syw.loginmodule.LoginApplication",
              "com.syw.memodule.MeApplication"
            };
        }
    
    
    • 现在我们需要在主项目中调用方法了,首先在主项目初始化的时候,通过initializa方法调用,已经让所有子项目setXxxService。
        public class MainApplication extends Application {
            @Override
            public void onCreate() {
                super.onCreate();
                for (String component : AppConfig.COMPONENT) {
                    try {
                        Class<?> clazz=Class.forName(component);
                        Object obj = clazz.newInstance();
                        if (obj instanceof Appcompat){
                            ((Appcompat) obj).initializa();
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
    
    • 在需要使用的地方,即可直接getXxxService,然后调用方法
        public class MainActivity extends AppCompatActivity {
    
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
    
                findViewById(R.id.gologin).setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        ServiceManager.getInstance().getLoginService().launch(MainActivity.this);
                    }
                });
    
                findViewById(R.id.gome).setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        ServiceManager.getInstance().getMeService().launch(MainActivity.this);
                    }
                });
    
                findViewById(R.id.gofragment).setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        Bundle bundle=new Bundle();
                        bundle.putString("name","张三");
                        ServiceManager.getInstance().getLoginService().invokeLoginFragment(getSupportFragmentManager(),R.id.container,bundle);
                    }
                });
            }
        }
    
    

    应该还可以参考阿里的aroute框架,目前先暂时记录到这里
    demo下载链接https://download.csdn.net/download/ForMuHan/13067005

    本文在开源项目:https://github.com/Android-Alvin/Android-LearningNotes 中已收录,里面包含不同方向的自学编程路线、面试题集合/面经、及系列技术文章等,资源持续更新中...

    相关文章

      网友评论

        本文标题:Android组件化开发的意义何在?

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