使用阿里ARouter路由實現元件化(模組化)開發流程
Android平臺中對頁面、服務提供路由功能的中介軟體,我的目標是 —— 簡單且夠用。
這是阿里對Arouter的定位,那麼我們一起來梳理一下Arouter使用流程,和使用中我所遇到的一些問題!
先來看看有哪些功能
模組化的要解決的問題
模組間頁面跳轉(路由);
模組間事件通訊;
模組間服務呼叫;
模組的獨立執行;
模組間頁面跳轉路由攔截(登入)
其他注意事項;
對專案模組進行劃分
app模組:主模組,主要進行搭載各個模組的功能。 lib_base:對ARouter進行初始化,和放置一些各個模組公用的封裝類。 lib_icon:放置圖片、assets、xml等公用資原始檔 module_home,module_caht,module_recom,module_me:分別對應“首頁”、“微聊”、“推薦”、“我的”模組!
ARouter各個模組的gradle配置
- 因為路由跳轉是子模組都需要用到的,所以我們在lib_base 模組中引入
compile 'com.alibaba:arouter-api:1.2.4'
annotationProcessor "com.alibaba:arouter-compiler:1.1.4"
包括整個專案中都會用到的其他依賴,例如:
compile 'com.android.support:design:26.0.0-alpha1'
compile 'org.simple:androideventbus:1.0.5.1'
compile 'com.alibaba:fastjson:1.2.9'
因為我把攔截器等公用類在base註冊,在編譯期間生成路徑對映。同時也需要在build中加入
defaultConfig {
javaCompileOptions {
annotationProcessorOptions {
arguments = [moduleName: project.getName()]
}
}
}
- 然後在各子模組的build檔案中匯入(也就是module_home,module_caht,module_recom,module_me):
/**
* 及時在base已經引入了com.alibaba:arouter-compiler:1.1.4
* 這裡也需要引入,不然報錯
*/
annotationProcessor 'com.alibaba:arouter-compiler:1.1.4'
compile project(':lib_base')
compile project(':lib_icon')
在編譯期間生成路徑對映。同時也需要在各子模組的build中加入:
defaultConfig {
javaCompileOptions {
annotationProcessorOptions {
arguments = [moduleName: project.getName()]
}
}
}
- 在app模組對各個子模組進行依賴:
compile project(':module_home')
compile project(':module_chat')
compile project(':module_recom')
compile project(':module_me')
模組可插拔單獨編譯執行
模組化的好處之一就是單一模組可以獨立的開發編譯執行安裝到使用者的手機上,這樣就方便了對某一模組的單獨開發除錯,單一模組生成的apk體積也小,編譯時間也快,開發效率會高很多。
- 專案根目錄gradle.properties配置:
# 是否需要單獨編譯 true表示不需要,false表示需要
isNeedHomeModule=true
#isNeedHomeModule=false
isNeedChatModule=true
#isNeedChatModule=false
isNeedRecomModule=true
#isNeedRecomModule=false
isNeedMeModule=true
#isNeedMeModule=false
- 在各個子模組中配置(例如module_me):
if (!isNeedMeModule.toBoolean()) {
apply plugin: 'com.android.application'
} else {
apply plugin: 'com.android.library'
}
defaultConfig {
if (!isNeedMeModule.toBoolean()) {
applicationId "tsou.cn.module_me"
}
}
- 在app主模組中:
if (isNeedHomeModule.toBoolean()) {
compile project(':module_home')
}
if (isNeedChatModule.toBoolean()) {
compile project(':module_chat')
}
if (isNeedRecomModule.toBoolean()) {
compile project(':module_recom')
}
if (isNeedMeModule.toBoolean()) {
compile project(':module_me')
}
如果需要單獨執行某個模組時,修改gradle.properties配置,
例如單獨執行module_home模組時,開啟isNeedHomeModule=false,
- 方式一:直接在AndroidManifest.xml的MainActivity新增
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
反之則關閉!當然比較lou
- 方式二:通過build自動配置
1、主目錄下AndroidManifest.xml不變
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="tsou.cn.module_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">
</activity>
</application>
</manifest>
2、在src目錄下建立debug資料夾包含一個AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="tsou.cn.module_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>
3、在子模組的build中配置
android {
...
sourceSets {
main {
if (!isNeedHomeModule.toBoolean()) {
manifest.srcFile 'src/debug/AndroidManifest.xml'
} else {
manifest.srcFile 'src/main/AndroidManifest.xml'
java {
//全部Module一起編譯的時候剔除debug目錄
exclude '**/debug/**'
}
}
}
}
}
4、執行module_home即可
ARouter初始化
在lib_base中建立MyApplication
public class MyApplication extends Application {
/**
* 上下文
*/
private static MyApplication instance;
@Override
public void onCreate() {
super.onCreate();
instance = this;
initRouter(this);
}
public static Context getInstance() {
return instance;
}
private void initRouter(MyApplication mApplication) {
// 這兩行必須寫在init之前,否則這些配置在init過程中將無效
if (UIUtils.isApkInDebug(instance)) {
//列印日誌
ARouter.openLog();
//開啟除錯模式(如果在InstantRun模式下執行,必須開啟除錯模式!
//線上版本需要關閉,否則有安全風險)
ARouter.openDebug();
}
// 儘可能早,推薦在Application中初始化
ARouter.init(mApplication);
}
}
/**
* 判斷當前應用是否是debug狀態
*/
public static boolean isApkInDebug(Context context) {
try {
ApplicationInfo info = context.getApplicationInfo();
return (info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
} catch (Exception e) {
return false;
}
}
這裡要注意:如果你在debug模式下進行除錯程式碼,ARouter.openDebug();一定要呼叫,否則ARouter會出現無效情況。
首頁的搭建
使用ARouter來獲取到各個模組的Fragment
package tsou.cn.lib_base.utils;
/**
* Created by Administrator on 2017/12/4 0004.
*/
public class RouteUtils {
//獲得home模組fragment
public static final String Home_Fragment_Main = "/home/main";
//獲得chat模組fragment
public static final String Chat_Fragment_Main = "/chat/main";
//獲得Recom模組fragment
public static final String Recom_Fragment_Main = "/recom/main";
//獲得Me模組fragment
public static final String Me_Fragment_Main = "/me/main";
//跳轉到登入頁面
public static final String Me_Login = "/me/main/login";
//跳轉到eventBus資料接收頁面
public static final String Me_EventBus = "/me/main/EventBus";
//跳轉到TextOne資料接收頁面
public static final String Me_TextOne = "/me/main/TextOne";
//跳轉到Test公用頁面
public static final String Me_Test = "/me/main/Test";
//路由攔截
public static final String Me_Test2 = "/me/main/Test2";
//跳轉到webview頁面
public static final String Me_WebView = "/me/main/WebView";
//跳轉到依賴注入頁面
public static final String Me_Inject = "/me/main/Inject";
/**
* 依賴注入使用,注意:必須實現SerializationService進行註冊,
*/
public static final String Home_Json_Service = "/huangxiaoguo/json";
//跳轉ForResult
public static final String Chat_ForResult = "/chat/main/ForResult";
//模組間服務呼叫,呼叫chat模組的介面
public static final String Service_Chat = "/chat/service";
//路由攔截
public static final String Chat_Interceptor = "/chat/main/Interceptor";
/**
* 專門的分組,這裡就叫做needLogin組,凡是在這個組下的,都會進行登入操作
*/
public static final String NeedLogin_Test3 = "/needLogin/main/Test3";
}
package tsou.cn.myaroutertest.utils;
import android.support.v4.app.Fragment;
import com.alibaba.android.arouter.launcher.ARouter;
import tsou.cn.lib_base.utils.RouteUtils;
/**
* Created by Administrator on 2017/12/4 0004.
*/
public class FragmentUtils {
public static Fragment getHomeFragment() {
Fragment fragment = (Fragment) ARouter.getInstance().build(RouteUtils.Home_Fragment_Main).navigation();
return fragment;
}
public static Fragment getChatFragment() {
Fragment fragment = (Fragment) ARouter.getInstance().build(RouteUtils.Chat_Fragment_Main).navigation();
return fragment;
}
public static Fragment getRecomFragment() {
Fragment fragment = (Fragment) ARouter.getInstance().build(RouteUtils.Recom_Fragment_Main).navigation();
return fragment;
}
public static Fragment getMeFragment() {
Fragment fragment = (Fragment) ARouter.getInstance().build(RouteUtils.Me_Fragment_Main).navigation();
return fragment;
}
}
package tsou.cn.myaroutertest;
import android.os.Bundle;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
import tsou.cn.myaroutertest.utils.FragmentUtils;
public class MainActivity extends AppCompatActivity {
private ViewPager mMViewPager;
private TabLayout mToolbarTab;
/**
* 圖示
*/
private int[] tabIcons = {
R.drawable.tab_home,
R.drawable.tab_weichat,
R.drawable.tab_recommend,
R.drawable.tab_user
};
private String[] tab_array;
private DemandAdapter mDemandAdapter;
private ArrayList<Fragment> fragments = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
initView();
// 給viewpager設定介面卡
setViewPagerAdapter();
setTabBindViewPager();
setItem();
}
private void initData() {
tab_array = getResources().getStringArray(R.array.tab_main);
fragments.clear();
fragments.add(FragmentUtils.getHomeFragment());
fragments.add(FragmentUtils.getChatFragment());
fragments.add(FragmentUtils.getRecomFragment());
fragments.add(FragmentUtils.getMeFragment());
}
private void initView() {
mMViewPager = (ViewPager) findViewById(R.id.mViewPager);
mToolbarTab = (TabLayout) findViewById(R.id.toolbar_tab);
}
private void setViewPagerAdapter() {
mDemandAdapter = new DemandAdapter(getSupportFragmentManager());
mMViewPager.setAdapter(mDemandAdapter);
}
private void setTabBindViewPager() {
mToolbarTab.setupWithViewPager(mMViewPager);
}
private void setItem() {
/**
* 一定要在設定介面卡之後設定Icon
*/
for (int i = 0; i < mToolbarTab.getTabCount(); i++) {
mToolbarTab.getTabAt(i).setCustomView(getTabView(i));
}
}
public View getTabView(int position) {
View view = LayoutInflater.from(this).inflate(R.layout.item_tab, null);
ImageView tab_image = view.findViewById(R.id.tab_image);
TextView tab_text = view.findViewById(R.id.tab_text);
tab_image.setImageResource(tabIcons[position]);
tab_text.setText(tab_array[position]);
return view;
}
/**
* 介面卡
*/
public class DemandAdapter extends FragmentStatePagerAdapter {
public DemandAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
return fragments.get(position);
}
@Override
public int getCount() {
return fragments.size();
}
}
}
程式碼中有註釋,切很簡單,不會出現什麼毛病!如果有小毛病,就clean一下解決
使用ARouter路由實現各種功能
跨模組跳轉Activity
實現這個Activity跳轉的路徑。
//跳轉到我的模組登入頁面
public static final String Me_Login = "/me/main/login";
ARouter跳轉Activity,在這個Activity上加入註解。
@Route(path = RouteUtils.Me_Login)
public class LoginActivity extends AppCompatActivity implements View.OnClickListener {
跳轉邏輯是
//登入(跨模組跳轉Activity)
ARouter.getInstance().build(RouteUtils.Me_Login).navigation();
跨模組實現ForResult返回資料(activity中使用)
實現這個Activity跳轉的路徑。
//跳轉ForResult
public static final String Chat_ForResult = "/chat/main/ForResult";
ARouter跳轉Activity,在這個Activity上加入註解。
@Route(path = RouteUtils.Chat_ForResult)
public class ForResultActivity extends AppCompatActivity implements View.OnClickListener {
跳轉邏輯是
//跳轉ForResult,在fragment中使用不起作用
ARouter.getInstance().build(RouteUtils.Chat_ForResult).navigation(this, 666);
接收資料資料
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode) {
case 666:
String name = data.getStringExtra("name");
UIUtils.showToast(name + ",resultCode===>" + resultCode);
break;
default:
break;
}
}
返回資料
Intent intent = new Intent();
intent.putExtra("name", "ForResult返回的資料");
setResult(999, intent);
finish();
- 跳轉並攜帶引數和Eventbus誇模組通訊
EventBus.getDefault().register(this);
EventBus.getDefault().unregister(this);
@Subscriber(tag = EvenBusTag.GOTO_EVENTBUS)
public void onEvent(String s) {
UIUtils.showToast(s);
}
//跳轉到eventBus資料接收頁面
public static final String Me_EventBus = "/me/main/EventBus";
@Route(path = RouteUtils.Me_EventBus)
public class EventBusActivity extends AppCompatActivity implements View.OnClickListener {
// 跳轉並攜帶引數,基本涵蓋所以型別傳遞,具體可以檢視Postcard類
//傳遞過去的值使用getIntent()接收
//在fragment中無法使用ForResult進行誇模組傳遞資料
//在activity中可以(詳細請看LoginActivity)這裡的EventBusBean 已經實現了Parcelable介面
EventBusBean eventBusBean = new EventBusBean();
eventBusBean.setProject("android");
eventBusBean.setNum(3);
ARouter.getInstance().build(RouteUtils.Me_EventBus)
.withString("name", "haungxiaoguo")
.withLong("age", 25)
.withParcelable("eventbus", eventBusBean)
.navigation();
@Route(path = RouteUtils.Me_EventBus)
public class EventBusActivity extends AppCompatActivity implements View.OnClickListener {
/**
* eventBus資料接收頁面
*/
private TextView mTextView;
/**
* eventBus返回資料
*/
private Button mBtnBackData;
private String name;
private long age;
private EventBusBean eventbus;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_event_bus);
ARouter.getInstance().inject(this);
initData();
initView();
}
private void initData() {
name = getIntent().getStringExtra("name");
age = getIntent().getLongExtra("age", 0);
eventbus = getIntent().getParcelableExtra("eventbus");
}
private void initView() {
mTextView = (TextView) findViewById(R.id.textView);
mBtnBackData = (Button) findViewById(R.id.btn_back_data);
mBtnBackData.setOnClickListener(this);
mTextView.setText("name=" + name + ",\tage=" + age + ",\tproject=" + eventbus.getProject() +
",\tnum=" + eventbus.getNum());
}
@Override
public void onClick(View v) {
int i = v.getId();
if (i == R.id.btn_back_data) {
EventBus.getDefault().post(name, EvenBusTag.GOTO_EVENTBUS);
finish();
} else {
}
}
}
路徑配置都是一樣,以下只介紹跳轉方式
- 使用Uri應用內跳轉
EventBusBean eventBusBean = new EventBusBean();
eventBusBean.setProject("android");
eventBusBean.setNum(3);
Uri testUriMix = Uri.parse("arouter://tsou.cn.huangxiaoguo/me/main/EventBus");
ARouter.getInstance().build(testUriMix)
.withString("name", "haungxiaoguo")
.withLong("age", 25)
.withParcelable("eventbus", eventBusBean)
.navigation();
- 舊版本轉場動畫
//舊版本轉場動畫
ARouter.getInstance()
.build(RouteUtils.Me_Test)
.withTransition(R.anim.slide_in_bottom, R.anim.slide_out_bottom)
.navigation(getContext());//context上下文不傳無效果
- 新版本轉場動畫
//新版本轉場動畫
if (Build.VERSION.SDK_INT >= 16) {
ActivityOptionsCompat compat = ActivityOptionsCompat.
makeScaleUpAnimation(v, v.getWidth() / 2, v.getHeight() / 2, 0, 0);
ARouter.getInstance()
.build(RouteUtils.Me_Test)
.withOptionsCompat(compat)
.navigation();
} else {
UIUtils.showToast("API < 16,不支援新版本動畫");
}
- 通過URL跳轉(webview)
//通過URL跳轉(webview)
ARouter.getInstance()
.build(RouteUtils.Me_WebView)
.withString("url", "file:///android_asset/schame-test.html")
.navigation();
攔截器操作
首先實現IInterceptor:
package tsou.cn.lib_base.interceptor;
import android.content.Context;
import android.util.Log;
import com.alibaba.android.arouter.facade.Postcard;
import com.alibaba.android.arouter.facade.annotation.Interceptor;
import com.alibaba.android.arouter.facade.callback.InterceptorCallback;
import com.alibaba.android.arouter.facade.template.IInterceptor;
import com.alibaba.android.arouter.launcher.ARouter;
import tsou.cn.lib_base.utils.RouteUtils;
/**
* Created by Administrator on 2017/12/6 0006.
* 新增攔截器的時候,建議clean再打包執行,不然會出現,無效的情況
* <p>
* 切記一個專案裡面priority的值保證唯一,不然會出毛病
*/
@Interceptor(priority = 1, name = "重新分組進行攔截")
public class MyDataInterceptor implements IInterceptor {
@Override
public void process(Postcard postcard, InterceptorCallback callback) {
if (postcard.getGroup().equals("needLogin")) {
Log.e("huangxiaoguo", "需要去登陸");
//直接執行
// callback.onContinue(postcard);
//直接攔截,走onLost方法
// callback.onInterrupt(null);
//新增資料
// postcard.withString("extra", "我是在攔截器中附加的引數");
// callback.onContinue(postcard);
callback.onInterrupt(null);
ARouter.getInstance().build(RouteUtils.Me_Login)
.withString("path", postcard.getPath()).navigation();
} else {
postcard.withString("extra", "我是在攔截器中附加的引數");
callback.onContinue(postcard);
}
}
@Override
public void init(Context context) {
}
}
接收未攔截時攔截器新增的資料(postcard.withString(“extra”, “我是在攔截器中附加的引數”);)
private void initData() {
extra = getIntent().getStringExtra("extra");
}
對目標Activity指定新的分組(組名為“needLogin”,注意同時也是“me”組下的成員)
@Route(path = RouteUtils.Me_Test2, group = "needLogin")
public class Test2Activity extends AppCompatActivity {
- 攔截器操作(利用重新分組攔截)
/**
* 如果利用重新分組,就需要在build中進行指定的分組不然沒有效果
*/
ARouter.getInstance()
.build(RouteUtils.Me_Test2, "needLogin")
.navigation(getContext(), new NavCallback() {
@Override
public void onFound(Postcard postcard) {
super.onFound(postcard);
//路由目標被發現時呼叫
Log.e("huangxiaoguo", "發現了");
}
@Override
public void onLost(Postcard postcard) {
super.onLost(postcard);
//路由被丟失時呼叫
Log.e("huangxiaoguo", "丟失了");
}
@Override
public void onArrival(Postcard postcard) {
//路由到達之後呼叫
Log.e("huangxiaoguo", "到達了");
}
@Override
public void onInterrupt(Postcard postcard) {
super.onInterrupt(postcard);
//路由被攔截時呼叫
Log.e("huangxiaoguo", "攔截了");
}
});
- 攔截器操作(利用原有分組)
/**
* 專門的分組,這裡就叫做needLogin組,凡是在這個組下的,都會進行登入操作
*/
public static final String NeedLogin_Test3 = "/needLogin/main/Test3";
@Route(path = RouteUtils.NeedLogin_Test3)
public class Test3Activity extends AppCompatActivity {
//攔截器操作(利用原有分組)
ARouter.getInstance().build(RouteUtils.NeedLogin_Test3).navigation();
- 攔截器操作(綠色通道,跳過攔截器)
//攔截器操作(綠色通道,跳過攔截器)
ARouter.getInstance().build(RouteUtils.NeedLogin_Test3)
.withString("extra", "我是綠色通道直接過來的,不經過攔截器")
.greenChannel()
.navigation();
- 依賴注入
必須先初始化JsonServiceImpl實現SerializationService
package tsou.cn.lib_base.JsonService;
import android.content.Context;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.alibaba.android.arouter.facade.service.SerializationService;
import com.alibaba.fastjson.JSON;
import java.lang.reflect.Type;
import tsou.cn.lib_base.utils.RouteUtils;
/**
* 依賴注入使用,注意:必須實現SerializationService進行註冊,
*/
@Route(path = RouteUtils.Home_Json_Service,name = "序列化JavaBean使用")
public class JsonServiceImpl implements SerializationService {
@Override
public void init(Context context) {
}
@Override
public <T> T json2Object(String text, Class<T> clazz) {
return JSON.parseObject(text, clazz);
}
@Override
public String object2Json(Object instance) {
return JSON.toJSONString(instance);
}
@Override
public <T> T parseObject(String input, Type clazz) {
return JSON.parseObject(input, clazz);
}
}
實現跳轉
/**
* 序列化過得
* 必須先初始化JsonServiceImpl實現SerializationService
*/
EventBusBean eventBusBean = new EventBusBean();
eventBusBean.setProject("android");
eventBusBean.setNum(3);
/**
* 普通的javaBean
*/
JavaBean javaBean = new JavaBean();
javaBean.setName("huangxiaoguo");
javaBean.setAge(25);
List<JavaBean> objList = new ArrayList<>();
objList.add(javaBean);
Map<String, List<JavaBean>> map = new HashMap<>();
map.put("testMap", objList);
ARouter.getInstance().build(RouteUtils.Me_Inject)
.withString("name", "老王")
.withInt("age", 18)
.withBoolean("boy", true)
.withLong("high", 180)
.withString("url", "https://www.baidu.com")
.withParcelable("pac", eventBusBean)
.withObject("obj", javaBean)
.withObject("objList", objList)
.withObject("map", map)
.navigation();
接收資料
package tsou.cn.module_me.activity;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.TextView;
import com.alibaba.android.arouter.facade.annotation.Autowired;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.alibaba.android.arouter.launcher.ARouter;
import java.util.List;
import java.util.Map;
import tsou.cn.lib_base.bean.EventBusBean;
import tsou.cn.lib_base.bean.JavaBean;
import tsou.cn.lib_base.utils.RouteUtils;
import tsou.cn.module_me.R;
/**
* 依賴注入使用,注意:必須實現SerializationService進行註冊,
*/
@Route(path = RouteUtils.Me_Inject)
public class InjectActivity extends AppCompatActivity {
@Autowired
String name = "hahahha";
@Autowired
int age = 13;
@Autowired(name = "boy")//對映引數名
boolean sex;
@Autowired
long high = 160;
@Autowired
String url;
@Autowired
EventBusBean pac;
@Autowired
JavaBean obj;
@Autowired
List<JavaBean> objList;
@Autowired
Map<String, List<JavaBean>> map;
@Autowired
int height = 21;//上頁面沒有傳遞
private TextView mTextView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_inject);
ARouter.getInstance().inject(this);
initView();
}
private void initView() {
mTextView = (TextView) findViewById(R.id.textView);
String params = String.format(
"name=%s,\n age=%s, \n height=%s,\n girl=%s,\n high=%s,\n url=%s,\n pac=%s,\n obj=%s \n" +
" objList=%s, \n map=%s",
name,
age,
height,
sex,
high,
url,
pac.getProject(),
obj.getName(),
objList.get(0).getName(),
map.get("testMap").get(0).getName()
);
mTextView.setText(params);
}
}
模組間服務呼叫
首先,為了所有子類模組都能共享這個方法,我們在lib_base中定義一個服務介面:
package tsou.cn.lib_base.provider;
import com.alibaba.android.arouter.facade.template.IProvider;
/**
* Created by Administrator on 2017/12/5 0005