模塊化開發步驟 + 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
完。
轉載請註明出處。