"XRouter" === 一種基於Arouter的使用封裝方案,實現對ARouter的Retrofit式使用。 "ARouter" 是阿裡巴巴開源的Android平臺中對頁面、服務提供路由功能的中間件, 沒用過的務必點擊 "傳送門" 基礎功能 1. 依賴配置 2. 給目標頁面添加註解 3. 在Ap ...
XRouter
一種基於Arouter的使用封裝方案,實現對ARouter的Retrofit式使用。
ARouter是阿裡巴巴開源的Android平臺中對頁面、服務提供路由功能的中間件,沒用過的務必點擊傳送門
基礎功能
1. 依賴配置
android {
defaultConfig {
...
javaCompileOptions {
annotationProcessorOptions {
arguments = [ moduleName : project.getName() ]
}
}
}
}
dependencies {
//ARouter
compile 'com.alibaba:arouter-api:x.x.x'
annotationProcessor 'com.alibaba:arouter-compiler:x.x.x'
//XRouter
compile 'com.mondyxue:xrouter:1.0-SNAPSHOT@aar'
}
repositories {
maven {
//XRouter
url "https://raw.githubusercontent.com/MondyXue/Maven/master"
}
}
2. 給目標頁面添加註解
import com.alibaba.android.arouter.facade.annotation.Route;
@Route(path = "/page/browser")
public class WebViewActivity extends BaseActivity{
...
}
3. 在Application中添加初始化代碼
//初始化uri信息
XRouter.setScheme("xrouter");
XRouter.setAuthority("mondyxue.github.io");
//XRouter初始化
XRouter.init(DemoApplication.this);
4. 聲明Navigator介面
import com.mondyxue.xrouter.annotation.Extra;
import com.mondyxue.xrouter.annotation.Route;
public interface WebNavigator{
@Route(path = "/page/browser")
void openUrl(@Extra("url") String url);
}
5. 發起路由
XRouter.getRouter()
.create(WebNavigator.class)
.openUrl("https://github.com/Alibaba/ARouter");
其它使用
XRouter基於ARouter提供了針對幾個常用場景的解決方案
Navigator
a. startActivityForResult
//聲明返回類型為ActivityNavigator<T>,T為需要解析的回傳數據類型
@Route(path = "/page/login")
ActivityNavigator<UserInfo> toLoginFragment();
//覆寫Activity和Fragment基類中的onActivityResult方法
public abstract class BaseActivity extends FragmentActivity{
...
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data){
super.onActivityResult(requestCode, resultCode, data);
//XRouter處理回調邏輯
XRouter.getRouter()
.getActivityManager()
.onActivityResult(BaseActivity.this, requestCode, resultCode, data);
}
}
//實現Callback
public abstract class UserInfoCallback extends RouteCallback<UserInfo>{
@Override public UserInfo parseData(int requestCode, int resultCode, Intent data){
return (UserInfo) data.getSerializableExtra(Extras.UserInfo);
}
}
//路由發起
XRouter.getRouter()
create(DemoNavigator.class)
toLoginFragment()
startActivityForResult(new UserInfoCallback(){
@Override public void onResponse(@NonNull UserInfo data){
Toast.makeText(MainActivity.this, "login success: " + data.toString(), Toast.LENGTH_SHORT).show();
}
});
b. 獲取服務
//聲明
@Route(path = "/service/userService")
UserService getUserService();
//創建navigator
DemoNavigator navigator = XRouter.getRouter().create(DemoNavigator.class);
//獲取UserService
UserService userService = navigator.getUserService();
boolean isLogin = userService.isLogin();
UserInfo userInfo = userService.getUserInfo();
//獲取Logger
Logger logger = navigator.getLogger();
logger.e("tag", "msg...");
c. 如果還不滿足,繼續組合打法
import com.mondyxue.xrouter.navigator.Navigator;
//聲明返回類型為Navigator
@Route(path = "/page/login")
Navigator toLoginFragment();
//創建Navigator
Navigator navigator = XRouter.getRouter()
.create(DemoNavigator.class)
.toLoginFragment();
//通過Navigator調用支持方法
Uri uri = navigator.uri();
Intent intent = navigator.intent();
Fragment fragment = navigator.fragment();
IProvider provider = navigator.service();
navigator.startActivity();
RouteType
import com.mondyxue.xrouter.constant.RouteType;
import com.alibaba.android.arouter.facade.annotation.Route;
//在ARouter的Route註解中
//RouteType中有幾個輔助flag值,可用於ARouter的Route註解中的extras值Route(extras=...)
RouteType.GreenChannel//綠色通道,不經過攔截器
RouteType.Fragment//Fragment標記
RouteType.Activity//Activity標記
RouteType.Service//標記是否為實現了IProvider的服務類
RouteType.WithinTitlebar//標記此頁面是否已有標題欄(Toolbar等)
RouteType.Login//標記訪問此頁面是否需要登錄許可權
RouteType.Main//標記此頁面是否為App首頁
//組合打法
RouteType.TitlebarFragment = Fragment | WithinTitlebar;
RouteType.LoginActivity = Activity | Login;
1. 登錄攔截
a. 配置extras標記
@Route(path = "/page/userInfo", extras = RouteType.LoginFragment)
public class UserInfoFragment extends BaseFragment{
...
}
b. 實現登錄攔截器
@Interceptor(priority = 4, name = "LoginInterceptor")
public class LoginInterceptor extends com.mondyxue.xrouter.interceptor.LoginInterceptor implements IInterceptor{
//返回當前用戶是否已登錄
@Override public boolean isLogin(){
return XRouter.getRouter()
.create(DemoNavigator.class)
.getUserService()
.isLogin();
}
//調用登錄服務,在登錄回調中執行原攔截器回調
@Override protected void onInterrupt(final Postcard postcard, final InterceptorCallback callback){
XRouter.getRouter()
.create(DemoNavigator.class)
.toLoginFragment()
.startActivityForResult(new UserInfoCallback(){
@Override public void onResponse(@NonNull UserInfo data){
postcard.withSerializable(Extras.UserInfo, data);
callback.onContinue(postcard);
}
@Override public void onError(Throwable throwable){
callback.onInterrupt(throwable);
}
@Override public void onCancel(){
callback.onInterrupt(new RuntimeException("login cancel!"));
}
});
}
}
2. Fragment攔截
a. 配置extras標記
@Route(path = "/page/text", extras = RouteType.Fragment)
public class TextFragment extends BaseFragment{
...
}
b. 配置Fragment容器Activity
@Route(path = "/page/contanier", extras = RouteType.Activity | RouteType.GreenChannel)
public class ContanierActivity extends BaseActivity{
@Override protected int getRootLayout(){
//RouteType.Titlebar標記值可通過此方式獲取
boolean withinTitlebar = getIntent().getBooleanExtra(RouteExtras.WithinTitlebar, false);
//根據標記值決定容器的佈局是否有標題欄
return withinTitlebar ? R.layout.activity_contanier
: R.layout.activity_contanier_within_titlebar;
}
@Override protected void init(){
Intent intent = getIntent();
boolean withinTitlebar = intent.getBooleanExtra(RouteExtras.WithinTitlebar, false);
if(!withinTitlebar){
//判斷並設置Title
String title = intent.getStringExtra(RouteExtras.Title);
((TextView) findViewById(R.id.tv_title)).setText(title);
}
//獲取攔截器中傳過來的Fragment路由path
String path = intent.getStringExtra(RouteExtras.PathTo);
if(!TextUtils.isEmpty(path)){
//使用XRouter根據path獲取fragment實例
final Fragment fragment = XRouter.getRouter().build(path).navigator().fragment();
if(fragment != null){
fragment.setArguments(intent.getExtras());
runOnUiThread(new Runnable(){
@Override public void run(){
getSupportFragmentManager()
.beginTransaction()
.add(R.id.fl_contanier, fragment)
.hide(fragment)
.show(fragment)
.commitAllowingStateLoss();
}
});
return;
}
}
finish();
}
}
c. 實現Fragment攔截器
@Interceptor(priority = 8, name = "FragmentInterceptor")
public class FragmentInterceptor extends com.mondyxue.xrouter.interceptor.FragmentInterceptor implements IInterceptor{
@Override protected String getFragmentContainerPath(){
//返回Fragment容器Activity路徑
return "/page/contanier";
}
}
還有個MainIntercepter,可用於主界面(RouteType.Main)的跳轉攔截,詳見Demo代碼
混淆
如果你使用混淆並且用到Fragment攔截器的話,需要在混淆配置中添加以下規則:
#XRouter:使用Fragment攔截器
-keep class com.alibaba.android.arouter.facade.Postcard{*;}
後話
小弟不才,第一次分享代碼到Github,碼代碼這茬,一個人容易出事,而且項目來不及寫註釋,所以特此貼上Q群二維碼,如果大家有什麼建議和槽點,歡迎能夠多多交流。