XRouter-像Retrofit一樣使用阿裡開源路由中間件

来源:http://www.cnblogs.com/MondyXue/archive/2017/07/26/7241459.html
-Advertisement-
Play Games

"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提供了針對幾個常用場景的解決方案

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群二維碼,如果大家有什麼建議和槽點,歡迎能夠多多交流。

Demo源碼Demo下載


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1. 如何創建嵌套的過濾器 //允許你減少集合中的匹配元素的過濾器, //只剩下那些與給定的選擇器匹配的部分。在這種情況下, //查詢刪除了任何沒(:not)有(:has) //包含class為“selected”(.selected)的子節點。 .filter(":not(:has(.select ...
  • Atwood’s Law是Jeff Atwood在2007年提出的:“any application that can be written in JavaScript, will eventually be written in JavaScript.”。據說,這隻是當時開的一個玩笑。不過,這個玩 ...
  • 使用Android DataBinding簡化Adapter的開發 ...
  • 它是如何觸發的? 這個值的狀態是燒錄在主板上,無法刷寫修改, 從0到1 不可逆,除非替換硬體 If a non-Knox boot loader or kernel has been installed on the device, Knox can no longer guarantee the ...
  • 一,效果圖。 二,工程圖。 三,代碼。 ViewController.h ViewController.m ...
  • Android Studio是官方推出的Android開發IDE,本系列講解Android Studio中常用的快捷鍵,本文是該系列的第一篇,講解的內容是與編輯代碼相關的快捷鍵。 本文所講快捷鍵基於Android Studio2.3.3 windows版本。 本文所記錄的快捷鍵皆親自實踐,全部可用。 ...
  • Mac PlantUML 安裝教程: http://blog.csdn.net/linuxcjh/article/details/51105294 為了簡化使用,可以在 Sublime 里配置個快捷鍵。打開 Preferences -> Key Binding - User,添加一個快捷鍵: { " ...
  • iOS響應鏈,UIResponder Chain,事件傳遞鏈,事件響應鏈 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...