我們上一篇文章是自定義Router,沒有看過的小伙伴自定義Router,但今天我們來看一看世面上主流的路由框架-由阿里推出的ARouter.。
參考資料:
https://mp.weixin.qq.com/s/hUKEOp3qa4C53F6ZmPuXjQ
https://mp.weixin.qq.com/s/UljVdlGQuwooVEJz_rctjw
1.項目引入
- 1.1首先在app的buildgradle添加以下依賴和配置:
配置在defaultConfig:
/* ARouter的配置*/
javaCompileOptions {
annotationProcessorOptions {
arguments = [AROUTER_MODULE_NAME: project.getName()]
}
}
依賴版本:
//ARouter的依賴
implementation 'com.alibaba:arouter-api:1.3.1'
annotationProcessor 'com.alibaba:arouter-compiler:1.2.0'
- 1.2 代碼初始化
public class BaseApplication extends Application {
//是否開啟調試
private static boolean isDebug =true;
@Override
public void onCreate() {
super.onCreate();
//必須在初始化之前寫入這兩行
if (isDebug) {
//打印日志
ARouter.openLog();
//開始調試
ARouter.openDebug();
}
//ARouter的實例化
ARouter.init(this);
}
}
2.常見功能實現
2.1 Activity的跳轉
2.1.1 Activity的普通跳轉
通常我們都是用startActivity()來進行Activtiy的跳轉,我們今天試試路由如何實現。
比如我們的MainActivity要跳轉到LoginActivity,那么我們就需要在支持路由的頁面上添加注解,如下:
這個path的值可以理解如果要跳轉LgoinActivity,告訴對方它的位置。
注意:路徑至少需要兩個級別:/ xx / xx
那我們MainActivity點擊跳轉的代碼如下:
這樣就可以實現Activity的跳轉了,但我們平時在開發中通常會自定義一個常量類來管理Path,如下:
public class Constants {
//loginActivity的path
public static final String LOGINPATH="/app/login";
//MainActivity的path
public static final String MAINPATH="/app/main";
}
所以我們之前的代碼就可以替換為:
ARouter.getInstance().build(Constants.LOGINPATH).navigation();
2.1.2 Activity通過Uri的跳轉
剛才的代碼可以這樣寫:
2.1.3 Fragement的跳轉
Fragment的跳轉和Activity相似,先強轉在跳轉,如:
Fragment fragment = (Fragment) ARouter.getInstance().build(Constance.ACTIVITY_URL_FRAGMENT).navigation()
2.2 Activity的跳轉攜參
首先我們需要在Activity的setContentView()方法后進行依賴注入(這個注入可以提取的Base中):
ARouter.getInstance().inject(this);
那么我們如何攜參跳轉呢:主要是withxxx()方法,如下:
那我們看看目標界面如何接收數據?
目標界面主要通過使用Autowired注解接受數據,如下:
直接打印即可:
Log.e(TAG,name+age+userBean.getUserMessage());
注意:
只有當@Autowired(name = "key"),也就是key標簽一致的情況下,才可以獲取到對象的值,所以為了規避每一個可能會遇到的風險,建議在@Autowired里面 都寫上與之對應具體的key名
2.3 ARouter之攔截器
2.3.1首先我們自定義攔截器,先implements IInterceptor .
我們來分析一下這個攔截器,首先要實現個方法:
- process() ,中斷路由進程
- init() ,攔截器初始化,此方法在sdk初始化時調用,只調用一次
還有Interceptor類注解里的priority即優先級:
priority這個優先級的數值越小,越先執行,優先級越高值越大,(四大組件中的廣播,優先級的取值是-1000到1000,數值越大優先級越高)。如果兩個攔截器的優先級一樣,項目編譯就會報錯。所以,不同攔截器定義的優先級屬性值不能相同。
ok,我們現在來看一眼代碼:
btnJumpLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Uri uri =Uri.parse(Constants.LOGINPATH);
ARouter.getInstance().build(uri)
.withString("name","張三") //傳String
.withInt("age",20)//傳Int
.withParcelable("userbean",new UserBean("家住大城市鐵嶺"))
.navigation(MainActivity.this, new NavigationCallback() {
@Override
public void onFound(Postcard postcard) {
//路由目標被發現時調用
Log.e(TAG, "路由目標被發現時調用" );
}
@Override
public void onLost(Postcard postcard) {
//路由被丟失時調用
Log.e(TAG, "路由被丟失時調用" );
}
@Override
public void onArrival(Postcard postcard) {
//路由到達之后調用
Log.e(TAG, "路由到達之后調用" );
}
@Override
public void onInterrupt(Postcard postcard) {
//路由被攔截時調用
Log.e(TAG, "路由被攔截時調用" );
}
});
}
});
咦,怎么多了個NavigationCallback回調接口?它跟攔截器有什么聯系呢?
我們運行一下看看打印信息:
問題出現了:我在點擊跳轉按鈕后,并沒有跳轉到LoginActivity的頁面。
想必同志們也猜測到了:就是我們自定義的攔截器process的方法攔截了這次跳轉請求。
那該如何處理呢?我還想繼續跳轉到LoginActivity頁面?
我們再次打印信息:
我們現在也可以解答NavigationCallback接口的回調接口了。也就是我們注釋的含義:
2.3.2 NavigationCallback 和 IInterceptor的組合使用
通常我們在開發中會在每個接口里判斷用戶的是否進行了登陸即登陸后的cookie是否失效之類。那我們如何運用ARouter進行判斷呢?
首先我們需要自定義一個NavigationCallback 。
public class CustomNavigationCallback implements NavigationCallback {
private static final String TAG = "CustomNavigationCallbac";
Context mContext;
public CustomNavigationCallback(Context mContext) {
this.mContext = mContext;
}
@Override
public void onFound(Postcard postcard) {
//路由目標被發現時調用
Log.e(TAG, "路由目標被發現時調用" );
}
@Override
public void onLost(Postcard postcard) {
//路由被丟失時調用
Log.e(TAG, "路由被丟失時調用" );
}
@Override
public void onArrival(Postcard postcard) {
//路由到達之后調用
Log.e(TAG, "路由到達之后調用" );
}
@Override
public void onInterrupt(Postcard postcard) {
//路由被攔截時調用
Log.e(TAG, "路由被攔截時調用" );
}
}
其次我們定義一個簡單的基類Activity,做一個簡單的封裝
public abstract class BaseActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(setLayoutId() != 0){
setContentView(setLayoutId());
ARouter.getInstance().inject(this);
initView();
initData();
}
}
/**
* 不帶參數跳轉
* @param context
* @param path
*/
public static void toActivity(final Context context, String path) {
ARouter.getInstance().build(path).navigation(context, new CustomNavigationCallback(context));
}
/**
* 帶參數跳轉
* @param context
* @param path
* @param bundle
*/
public static void toActivity(final Context context, String path, Bundle bundle) {
ARouter.getInstance().build(path)
.withBundle("data", bundle).navigation(context, new CustomNavigationCallback(context));
}
public abstract int setLayoutId();
public abstract void initView();
public abstract void initData();
}
到此我們還要先定義一個策略,控制是否頁面需要登陸,進而在判斷是否已經進行了登陸。
以MainActivity界面為例,如果我們需要MainActivity界面登陸那么可以這樣寫:
CustomInterceptor核心代碼如下:
在CustomNavigationCallback的onInterrupt方法中,我們簡單toast一下:
2.4 ARouter實現StartActivityForResult()?
- 第一步,現在MainActivity重寫onActivityResult().
btnStartActivity.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
ARouter.getInstance().build(Constants.LOGINPATH).navigation(MainActivity.this,123,new CustomNavigationCallback(MainActivity.this));
}
});
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (resultCode){
case 456:
tvShow.setText("接受到的數據是:"+data.getStringExtra("data"));
break;
}
}
- 第二步,在LoginActivity的setRuslt()
Intent mIntent =new Intent().putExtra("data","456");
setResult(456,mIntent);
finish();
過于簡單我就不解釋了。
demo以上傳Github,點我傳送。
基本就這樣,好多用法自己去看文檔,看不懂英文有中文的,拜拜。