模块化开发步骤 + ARouter的使用 + 结合mvp结构分模块(一)
模块化开发步骤 + ARouter的使用 + 结合mvp结构分模块(二)
模块化开发步骤 + ARouter的使用 + 结合mvp结构分模块(三)
接下来我们结合MVP模式结构分模块:
首先分模块我们知道模块间是不能互相调用的,所以自己封装的mvp结构和一些公用的底层封装我们新建模块的时候选择Library,里面放所有公用的东西,然后每个模块只要依赖它就可以了。
这一块需要结合我前面文章说的Retrofit+Rxjava封装的MVP来讲解
demo按导航栏中分4个模块+1个Library库。
1、mvp_library模块。以library模式存在,所以不用管它的AndroidManifest,只需要按模块化开发步骤中提到的SDK配置即可
1.1、关于bean的疑问:
mvp + api + utils 公用大家都比较容易理解,这个bean实体为何会在这里?
1、api接口声明的时候就已经需要声明这个实体了;
2、这些实体只是做数据的载体,没有任何逻辑,是可以复用的。
1.2、其他公用部分:
除了截图中的类文件,还有raw资源,第三方库的依赖,这些都是所有模块通用的,所以都放到这个library里面。
对第三方库的依赖需要特别注意,把所有其他模块会用到的第三方库的implementation改成api,只有自己模块才用的依赖就不用改。
这里顺便说一下implementation和api的区别:项目implementation依赖一个库(假设叫a库),则项目不能引用a库里面声明却没有用到的库,而api可以引用到。我们这里是自己的library引用这些第三方库来再被依赖到各个模块中使用,所以要用api。
1.3、ARouter依赖:
implementation 'com.alibaba:arouter-api:1.5.0'
annotationProcessor 'com.alibaba:arouter-compiler:1.2.2'
上面我们是把它们写在一起,但是在这里我们需要把它们分开,咱们这个library里只要添加第一个,api 'com.alibaba:arouter-api:1.5.0'。
annotationProcessor 这个是帮我们自动生成文件的东西,需要在各个模块里面分别写,才能生成本模块所需的文件。
对了,还有前面说的arguments = [AROUTER_MODULE_NAME: project.getName()]代码块也是分别在每个模块的build.gradle中写,本library中不需要写。
1.4、关于BaseArouter类:
BaseArouter类为分模块封装的类注解字符串路径常量,类里面再按模块分4个内部类,每个内部类里面写自己的Activity或者Fragment的字符串
/**
* @author : xaeHu
* e-mail : [email protected]
* @date : 2019/8/13 12:07
* desc :Arouter类注解声明path常量
*/
public class BaseArouter {
/**
* 主页模块
*/
public class Home{
public final static String HomeFragment = "/Home/HomeFragment";
public final static String SearchActivity = "/Home/SearchActivity";
public final static String SearchDetailActivity = "/Home/SearchDetailActivity";
}
/**
* 个人中心模块
*/
public class Person{
public final static String PersonFragment = "/Person/PersonFragment";
}
······//其他模块
}
2、主模块。就是项目的app模块,这个模块是躯壳,只做欢迎页WecomeActivity或者界面启动的MainActivity还有Application的声明(或者还有微信SDK所需wxapi)。
说类之前先说一下他的AndroidManifest和build.gradle:
2.1、首先AndroidManifest只需要添加所有权限和改继承了Application的那个类名id给application元素:
<uses-permission android:name="android.permission.INTERNET" />
<application
android:name=".App"
······
2.2、build.gradle:
2.2.1、上面说的SDK版本配置
2.2.2、阿里ARouter配置
android{
······
javaCompileOptions {
annotationProcessorOptions {
arguments = [AROUTER_MODULE_NAME: project.getName()]
}
}
······
}
2.2.3、依赖:
dependencies{
······
api project(':mvp_library')
annotationProcessor 'com.alibaba:arouter-compiler:1.2.2'
if(!MODULE_IS_APPLICATION.toBoolean()){
implementation project(':home_module')
implementation project(':search_module')
implementation project(':detail_module')
implementation project(':person_module')
}
}
我这个模块里面直接定义两个类,一个MainActivity,还有一个继承了Appalachian的App类。
2.3、MainActivity的界面是ViewPager+SlidingTabLayout,ViewPager放其他四个模块的主Fragment:
//private ViewPager viewpager;
//private SlidingTabLayout tab;
//private String []title = {"首页","搜索","详细搜索","个人中心"};
ArrayList<Fragment> fragmentList = new ArrayList<>();
fragmentList.add((Fragment) ARouter.getInstance().build(BaseArouter.Home.HomeFragment).navigation());
fragmentList.add((Fragment) ARouter.getInstance().build(BaseArouter.Search.SearchFragment).navigation());
fragmentList.add((Fragment) ARouter.getInstance().build(BaseArouter.Detail.SearchDetailFragment).navigation());
fragmentList.add((Fragment) ARouter.getInstance().build(BaseArouter.Person.PersonFragment).navigation());
tab.setViewPager(viewpager,title,this, fragmentList);
2.4、App类里面做必要的初始化:
public class App extends Application {
@Override
public void onCreate() {
super.onCreate();
// 这两行必须写在init之前,否则这些配置在init过程中将无效
if (BaseConstant.IS_DEBUG) {
ARouter.openLog(); // 打印日志
ARouter.openDebug(); // 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
}
// 尽可能早,推荐在Application中初始化
ARouter.init(this);
}
}
3、其他模块
AndroidManifest和build.gradle的修改如模块化开发步骤所说。
另外:需要添加library模块和ARouter配置:
android{
······
javaCompileOptions {
annotationProcessorOptions {
arguments = [AROUTER_MODULE_NAME: project.getName()]
}
}
······
}
······
dependencies {
······
api project(":mvp_library")
annotationProcessor 'com.alibaba:arouter-compiler:1.2.2'
}
Activity和Fragment的注解:
@Route(path = BaseArouter.Home.SearchActivity)
public class SearchActivity extends BaseActivity<SearchPresenter>
@Route(path = BaseArouter.Home.HomeFragment)
public class HomeFragment extends BaseFragment<HomeP>
最后,还有个关键的地方,如果你的模块可独立运行,那它得有入口,并且在主模块的App里初始化的东西这里也拿不到对吧。
所以我们可以利用新建模块的时候那个入口Activity类做这些:
界面只放一个FrameLayout布局,用于显示本模块最外层的这个Fragment。app里初始化的东西也都搬到这里初始化。
因为这个入口类只是做单独运行的时候用,打包的时候是不用的,所以我们不需给他添加ARouter的注解,我们不需要跳转到这个界面来。
public class HomeMainActivity extends BaseStaticActivity {
@Override
protected int getLayoutId() {
return R.layout.acticity_home;
}
@Override
protected void initView() {
}
@Override
protected void initData() {
// 这两行必须写在init之前,否则这些配置在init过程中将无效
if (BaseConstant.IS_DEBUG) {
ARouter.openLog(); // 打印日志
ARouter.openDebug(); // 开启调试模式(如果在InstantRun模式下运行,必须开启调试模式!线上版本需要关闭,否则有安全风险)
}
// 尽可能早,推荐在Application中初始化
ARouter.init(getApplication());
FragmentManager fm = getSupportFragmentManager();
if(fm != null) {
Fragment fragment = fm.findFragmentById(R.id.activity_home_fragment);
if(fragment == null){
fragment = new HomeFragment();
fm.beginTransaction().add(R.id.activity_home_fragment, fragment).commit();
}
}
}
@Override
protected void initListener() {
}
}
最后附上demo地址:github
完。
转载请注明出处。