目录
模块化的开发流程
-
首先 我们建立一个主App,主app用来控制触发进入各个模块的入口,只是一个外壳,所有的逻辑在各个模块组件内部开发,各个模块以及外壳的app通信是采用阿里的路由框架进行的,稍后我会搭建一个可以各个模块的配置,以及运行环境。大家直接实战进行吧,在网上搜索一堆的模块化开发博客,倒不如自己亲自实践一下,原理都是一样,实践出真知吧。
-
首先我的AS是3.6.1 版本的,我们搭建一个主工程,我这里暂且命名时StoreApp,然后再在这个主工程下面创建三个子module工程和一个lib工程,分别命名module工程为home,mine,store工程,lib工程名为baselib,而lib工程主要用来依赖各个工程所需要依赖的资源库 。创建好了这些以后,我们知道module工程是可以独立运行的。接下来,我们得配置module工程为lib库作为依赖了。
-
在主工程的 gradle.properties文件下配置值三个控制home,mine,store作为库工程还是独立调试的可运行的module工程。我是这样配置的三个参数的:
#控制子工程是以lib还是moudle的形式 isShowHome = true isShowMine = true isShowStore= true
- 三个module工程的gradle配置都是一样的配置,这里我以home为例。在gradle的顶部加一个if判断句:
if (!isShowHome.toBoolean()) { apply plugin: 'com.android.application' } else { apply plugin: 'com.android.library' } 这个是用来判断它为module还是lib库的 接下来在我们看到包名applicationId在其中也添加一个判断语句:
if (!isShowHome.toBoolean()) { applicationId "com.android.xzl.home" }
- 接下来我们配置一下清单文件的资源:
sourceSets { main { //控制两种模式下的资源和代码配置情况 if (!isShowHome.asBoolean()) { manifest.srcFile 'src/main/module/AndroidManifest.xml' } else { manifest.srcFile 'src/main/AndroidManifest.xml' //集成开发模式下排除debug文件夹中的所有Java文件 java { exclude 'debug/**' } } } } 我们看到有个路径,我们没有建立这个时候,在main目录下建立一个module文件夹,但是然后将我们清单文件复制一份进去,但是要做一些修改。将application下的各种配置都删除掉,然后就留下一个theme属性就行了。我给大家先贴出一份我的module工程下的清单文件,然后是建立的module文件夹下的清单文件代码: home的module工程下的清单文件:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.xzl.home"> <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=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> 而我们自己建立的文件夹的清单文件为:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.xzl.home"> <application android:theme="@style/AppTheme"> <activity android:name=".MainActivity"/> </application> </manifest>
- 好了,其余的mine和store的module工程gradle配置是一样的,但是要对应我们的之前在gradle.properties的配置的三个布尔值,记得把把那个改一下。当然我们也可以用一个布尔值配置三个moudle工程开关,这个看个人的喜欢。
- 接下来,我们配置一下baselib的库,首先我们用的是阿里的路由框架用来各个模块的通信,传参。在gradle中依赖一下:
api 'com.alibaba:arouter-api:1.4.1' annotationProcessor 'com.alibaba:arouter-compiler:1.2.1' 这里注意一下,我没有用implementation而是用了api,大家可以自行百度,看一下区别。接下来,我们在defaultConfig中还要加入:
javaCompileOptions { annotationProcessorOptions { arguments = [AROUTER_MODULE_NAME: project.getName()] } } 这下我们就配置好了路由框架了。这里有个注意点各个子工程要是用到路由框架都要再次在gradle中的依赖出加入:
annotationProcessor 'com.alibaba:arouter-compiler:1.2.1' 和
javaCompileOptions { annotationProcessorOptions { arguments = [AROUTER_MODULE_NAME: project.getName()] } }
这个依赖,不然编译的时候会报alibaba:arouter找不到的错误。
- 接下来,我们在baselib库下建立BaseApplication,
import com.alibaba.android.arouter.launcher.ARouter; public class BaseApplication extends Application { private static BaseApplication instance; @Override public void onCreate() { super.onCreate(); instance=this; initRouter(); } public static BaseApplication getInstance(){ return instance; } private void initRouter(){ if (BuildConfig.DEBUG) { //一定要在ARouter.init之前调用openDebug ARouter.openDebug(); ARouter.openLog(); } ARouter.init(this); } } 然后建立一个路劲类RouterPath:
/** * create by libo * create on 2018/12/25 * description 路径跳转配置类 */ public class RouterPath { public static final String ROUTER_HOME = "/home/activity"; public static final String ROUTER_MINE = "/mine/activity"; public static final String ROUTER_STORE = "/store/activity"; }
- 然后我们在主工程还有各个模块都依赖这个baselib
- 接下来我们在主工程的moudle下,
implementation project(path: ':baselib') annotationProcessor 'com.alibaba:arouter-compiler:1.2.1' implementation project(path: ':mine') implementation project(path: ':home') implementation project(path: ':store') 再次强调一下:使用路由框架还需要依赖:annotationProcessor 'com.alibaba:arouter-compiler:1.2.1'这个,还有加上
javaCompileOptions { annotationProcessorOptions { arguments = [AROUTER_MODULE_NAME: project.getName()] } }
- 然后我们在主工程建立MainApplication继承baselib库的BaseApplication,记住在清单文件中声明一下:代码:
/** * author : wulei * e-mail : * time : 2020/04/04 * desc : */ public class MainApplication extends BaseApplication { @Override public void onCreate() { super.onCreate(); } }
- 如果你的jdk版本过低,在各个模块的gradle中加入:
compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 }
- 然后你就可以写你的逻辑代码了我再我的主工程的MainActivity下的代码:
public class MainActivity extends AppCompatActivity implements View.OnClickListener { private Button mBtHome; private Button mBtMine; private Button mBtStore; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ARouter.getInstance().inject(this); mBtHome = (Button) findViewById(R.id.bt_home); mBtMine = (Button) findViewById(R.id.bt_mine); mBtStore = (Button) findViewById(R.id.bt_store); mBtHome.setOnClickListener(this); mBtMine.setOnClickListener(this); mBtStore.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.bt_home: ARouter.getInstance().build(RouterPath.ROUTER_HOME). withString("home_msg", "我传递了home页面过去").navigation(); break; case R.id.bt_mine: ARouter.getInstance().build(RouterPath.ROUTER_MINE). withString("mine_msg", "我是磊磊哥啊!!!!").navigation(); break; case R.id.bt_store: ARouter.getInstance().build(RouterPath.ROUTER_STORE). withString("store_msg", "进入了商店,买个东西再走吧!!!").navigation(); break; } } 布局文件如下:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" android:orientation="vertical"> <Button android:id="@+id/bt_home" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="跳转home界面"/> <Button android:id="@+id/bt_mine" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="跳转我的界面"/> <Button android:id="@+id/bt_store" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="跳转商店界面"/> </LinearLayout>
14.我的home页面的代码如下:
@Route(path = RouterPath.ROUTER_HOME) public class MainActivity extends AppCompatActivity { @Autowired() String home_msg; private TextView mTvHome; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_home); ARouter.getInstance().inject(this); mTvHome = (TextView) findViewById(R.id.tv_home); mTvHome.setText(home_msg+""); } }
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" android:gravity="center"> <TextView android:id="@+id/tv_home" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
15.在mine的逻辑代码如下:
@Route(path = RouterPath.ROUTER_MINE) public class MainActivity extends AppCompatActivity { @Autowired String mine_msg; private TextView mTvMine; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ARouter.getInstance().inject(this); setContentView(R.layout.activity_mine); mTvMine = (TextView) findViewById(R.id.tv_mine); mTvMine.setText(mine_msg); } }
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <TextView android:id="@+id/tv_mine" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="这是默认的我的界面!!!!" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
16:在store下的代码:
@Route(path= RouterPath.ROUTER_STORE) public class MainActivity extends AppCompatActivity { @Autowired String store_msg; private TextView mTvStore; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_store); ARouter.getInstance().inject(this); mTvStore = (TextView) findViewById(R.id.tv_store); mTvStore.setText(store_msg); } }
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <TextView android:id="@+id/tv_store" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="这是商店的默认界面!!!!!!" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
哈哈哈,最后警告一下,新建的module下的布局文件的名字不要全部一样的,到时候有冲突的额!!!接下来我们就可以试着运行项目了。