美文网首页Android技术知识Android开发
Android组件化开发的意义何在?

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

作者: Android开发工作者 | 来源:发表于2021-01-23 21:17 被阅读0次

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

项目结构解析

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

统一项目编译版本

  • gradle.properties文件设置统一版本
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n9" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> # 统一编译版本等信息
 compile_Sdk_Version=28
 min_Sdk_Version=15
 target_Sdk_Version=28
  • 修改app、loginmodule、memodule、mudulelibrary的编译版本,以app为例
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n13" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> 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文件设置切换开关
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n18" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> # application和library切换开关
 isLoginApplication=true
 isMeApplication=true
  • 主应用动态添加依赖
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n22" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> //不要忘记toBoolean()
 if (!isLoginApplication.toBoolean()) {
 implementation project(':loginmodule')
 }
 if (!isMeApplication.toBoolean()) {
 implementation project(':memodule')
 }
 implementation project(':modulelibrary')
  • 子应用切换application和library、动态设置applicationId、动态设置AndroidManifest.xml、添加基础依赖。以login模块为例
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n26" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> //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

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n28" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> <?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

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n32" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> public interface ILoginService {
 void launch(Context context);
​
 Fragment getFragment(FragmentManager fragmentManager, int containerId, Bundle bundle);
 }

编写接口管理类

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n34" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">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;
 }
}

子项目完成具体实现

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n36" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">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中通过如下代码调用

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n39" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> ServiceFactory.getInstance().getLoginService().launch(MainActivity.this);

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

在子项目中创建一个方法,在主项目初始化的时候,通过主项目调用,子项目将实现类设置给ServiceManager
  • 我们首先需要在基础库创建一个接口,通过主项目调用,实现全部子应用设置Service
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n45" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> public interface Appcompat {
 void initializa();
 }
  • 我们首先创建一个类,实现该接口,设置LoginService
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n49" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> public class LoginApplication extends Application implements Appcompat {
 @Override
 public void initializa() {
 ServiceManager.getInstance().setLoginService(new LoginBridge());
 }
 }
  • 我们创建一个类,管理所有子项目设置Service的类。主项目通过反射的方法调用,实现全部子应用设置Service
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n53" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> public class AppConfig {
 public static final String[] COMPONENT={
 "com.syw.loginmodule.LoginApplication",
 "com.syw.memodule.MeApplication"
 };
 }
  • 现在我们需要在主项目中调用方法了,首先在主项目初始化的时候,通过initializa方法调用,已经让所有子项目setXxxService。
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n57" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> 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,然后调用方法
<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" cid="n61" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"> 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

相关文章

  • Android 组件化开发实践

    Android组件化开发实践(一):为什么要进行组件化开发?Android组件化开发实践(二):组件化架构设计An...

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

    安卓组件化开发的意义 当项目比较大需要多人协同开发的时候,组件化开发可以使大家分模块开发,并且不会互相影响。并且可...

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

    安卓组件化开发的意义当项目比较大需要多人协同开发的时候,组件化开发可以使大家分模块开发,并且不会互相影响。并且可以...

  • 聊聊组件化开发

    如果你在京东图书频道搜索 组件化 或者 组件化开发,显示的几乎都是 Android组件化开发 或者 Android...

  • CC框架实践(2):Fragment和View的组件化

    前言 本文将介绍如何在CC框架下实现Fragment和View的组件化。 一、需求背景 在android组件化过程...

  • Gradle实战——组件化的gradle build优化

    组件化gradle build优化 关于组件化,大家可以看我之前的文章,Android组件化开发实战[https:...

  • Android组件化和插件化开发

    Android组件化和插件化开发 什么是组件化和插件化? 组件化开发 就是将一个app分成多个模块,每个模块都是一...

  • 推荐文章

    JavaJava中有关Null的9件事 AndroidAndroid组件化和插件化开发Android 组件化 ——...

  • android 收藏的一些好文

    1.常用git命令清单 2.Android组件化、模块化开发 3.Android 组件化案例 4. 5.

  • Android组件化和插件化开发

    Android组件化和插件化开发 什么是组件化和插件化? 组件化开发就是将一个app分成多个模块,每个模块都是一个...

网友评论

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

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