目录

  模块化的开发流程


  模块化的开发流程

  1.      首先 我们建立一个主App,主app用来控制触发进入各个模块的入口,只是一个外壳,所有的逻辑在各个模块组件内部开发,各个模块以及外壳的app通信是采用阿里的路由框架进行的,稍后我会搭建一个可以各个模块的配置,以及运行环境。大家直接实战进行吧,在网上搜索一堆的模块化开发博客,倒不如自己亲自实践一下,原理都是一样,实践出真知吧。
  2.     首先我的AS是3.6.1 版本的,我们搭建一个主工程,我这里暂且命名时StoreApp,然后再在这个主工程下面创建三个子module工程和一个lib工程,分别命名module工程为home,mine,store工程,lib工程名为baselib,而lib工程主要用来依赖各个工程所需要依赖的资源库 。创建好了这些以后,我们知道module工程是可以独立运行的。接下来,我们得配置module工程为lib库作为依赖了。
  3.  在主工程的 gradle.properties文件下配置值三个控制home,mine,store作为库工程还是独立调试的可运行的module工程。我是这样配置的三个参数的:
#控制子工程是以lib还是moudle的形式
isShowHome = true
isShowMine = true
isShowStore= true
  1. 三个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"
}
  1. 接下来我们配置一下清单文件的资源:
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>
  1. 好了,其余的mine和store的module工程gradle配置是一样的,但是要对应我们的之前在gradle.properties的配置的三个布尔值,记得把把那个改一下。当然我们也可以用一个布尔值配置三个moudle工程开关,这个看个人的喜欢。
  2. 接下来,我们配置一下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找不到的错误。
  1. 接下来,我们在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";
}
  1. 然后我们在主工程还有各个模块都依赖这个baselib
  2. 接下来我们在主工程的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()]
    }
}
  1. 然后我们在主工程建立MainApplication继承baselib库的BaseApplication,记住在清单文件中声明一下:代码:
/**
 * author : wulei
 * e-mail :
 * time   : 2020/04/04
 * desc   :
 */
public class MainApplication extends BaseApplication {

    @Override
    public void onCreate() {
        super.onCreate();
    }
}
  1. 如果你的jdk版本过低,在各个模块的gradle中加入:
compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
}
  1. 然后你就可以写你的逻辑代码了我再我的主工程的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下的布局文件的名字不要全部一样的,到时候有冲突的额!!!接下来我们就可以试着运行项目了。