首頁  >  文章  >  web前端  >  如何解決Router跨模組跳轉問題

如何解決Router跨模組跳轉問題

亚连
亚连原創
2018-06-12 16:16:232032瀏覽

開始模組化開發專案之後,一個很重要的問題就是頁面見的跳轉問題,這篇文章主要介紹了Router解決跨模組下的頁面跳轉範例,現在分享給大家,也給大家做個參考。

一、前言

開始模組化開發專案之後,一個很重要的問題就是頁面見的跳躍問題。

關於模組化髮開,可詳見我的另一片文章 Android模組化開發探索 。

正是由於將專案模組化拆分,各模組之間沒有任何依賴關係,也互相不可見,那麼從A模組的a介面跳到B模組的b介面該怎麼辦呢?

二、跨模組跳轉的方法

這裡我們會先介紹這幾種常見的跳轉方法:

  1. 顯示跳轉

  2. 已隱含跳轉

  3. #Scheme協定跳轉

  4. Router路由表方案

2.1 顯示跳轉

#顯示跳轉即我們最常用的跳轉方法:使用Intent,傳入當前Activity上下文,和目標Activity的class物件即可,如下:

Intent intent = new Intent();
intent.setClass(mContext, GuideActivity.class);
startActivity(intent);

顯然,這種方法只能是目標Activity可見(Activity在同一個Module下)的時候才可以這樣呼叫。不適合跨模組間的跳轉。

2.2 隱示跳轉

我們這裡說的隱示跳轉,intent不設定class,而是設定Action或Category。

例如:

在清單檔案中

<!--网页展示界面-->
<activity
  android:name="com.whaty.base.BaseWebViewActivity"
  android:hardwareAccelerated="true">
    <intent-filter>
      <category android:name="android.intent.category.DEFAULT" />
      <action android:name="com.whaty.base.BaseWebViewActivity" />
    </intent-filter>
</activity>

跳轉時:

//创建一个隐式的 Intent 对象:Action 动作 
Intent intent = new Intent(); 
//设置 Intent 的动作为清单中指定的action 
intent.setAction("com.whaty.base.BaseWebViewActivity"); 
startActivity(intent);

2.3 scheme跳轉

#如果我們為B 頁面定義一個URI - wsc://home/bbb,然後把共享的messageModel 拍平序列化成Json 串,那麼A 只需要拼裝一個符合B 頁面scheme 的跳轉協議就可以了。 wsc://home/bbb?message={ “name”:”John”, “age”:31, “city”:”New York” }

在清單檔案中,配置data屬性,設置其host、path、scheme等

<activity android:name=".ui.BbbActivity"
  <intent-filter>
    <category android:name="android.intent.category.DEFAULT" />
    <action android:name="android.intent.action.VIEW" />
    <data
      android:host="bbb"
      android:path="/home"
      android:scheme="wsc" />
  </intent-filter>
</activity>

跳轉時:

final Uri uri = new Uri.Builder().authority("wsc").path("home/bbb").appendQueryParameter("message", new Gson().toJson(messageModel)).build();
final Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(uri);
startActivity(intent);

以上的方法,都不是我們想要的,接下來開始介紹我們的Router方案。

三、為什麼要用Router

Google提供了明確和隱含兩種原生路由方案。但在模組化開發中,顯式Intent存在類別直接依賴的問題,造成模組間嚴重耦合。隱式Intent則需要在Manifest中配置大量路徑,導致難以拓展(如進行跳轉攔截)。為了解決以上問題,我們需要採用一套更靈活的Router方案。

四、實現思路

思路是這樣的:

#使用註解,為每個目標Activity標註別名。在應用程式啟動時,對所有類別進行掃名,將註解過的Activity存於路由表中。

跳轉時,在路由表中透過別名取得目標Activity的class對象,使用Intent實現跳躍。

五、程式碼實作

5.1 自訂註解

/**
 * Description: 路由跳转界面 注解
 * Created by jia on 2018/1/10.
 * 人之所以能,是相信能
 */
@Target(ElementType.TYPE) //注解作用于类型(类,接口,注解,枚举)
@Retention(RetentionPolicy.RUNTIME) //运行时保留,运行中可以处理
@Documented // 生成javadoc文件
public @interface Action {

  String DEFAULT = "js";

  String value() default DEFAULT;

}

關於自訂註解的詳細介紹,請閱讀我的文章java進階自訂註解。這裡不再多說。

5.2 註解Activity

@Action("MainActivity")
public class MainActivity extends BaseActivity implements TabLayout.OnTabSelectedListener {

  ...
}

在建立Activity時,用剛剛自訂的註解進行註解,為其註解別名。

5.3 啟動時掃描

private void getAllActivities(Context ctx){
  try {
    //通过资源路径获得DexFile
    DexFile e = new DexFile(ctx.getPackageResourcePath());
    Enumeration entries = e.entries();
    //遍历所有元素
    while(entries.hasMoreElements()) {
      String entryName = (String)entries.nextElement();
      //匹配Activity包名与类名
      if(entryName.contains("activity") && entryName.contains("Activity")) {
        //通过反射获得Activity类
        Class entryClass = Class.forName(entryName);
        if(entryClass.isAnnotationPresent(Action.class)) {
          Action action = (Action)entryClass.getAnnotation(Action.class);
          this.map.put(action.value(), entryClass);
        }
      }
    }
  } catch (Exception e) {
    e.printStackTrace();
  }
}

在應用程式啟動時,Application中會對套件下的所有類別進行掃描,先找到名字中到activity的(定義到activity套件下),並將有註解標註的Activity,存入map。

5.4 跳轉

/**
 * 页面跳转
 * @param activity
 * @param alias
 */
public void jumpActivity(Activity activity, String alias) throws ClassNotFoundException{
  if(map.containsKey(alias)) {
    Intent intent = new Intent(activity, map.get(alias));
    activity.startActivity(intent);
  } else {
    throw new ClassNotFoundException();
  }
}

跳轉的時候傳入目標Activity的別名即可(這裡的別名就是註解的別名)。

總結

透過這種方式,解決了跳躍Activity所產生的模組依賴的問題,相較於原生方案,拓展性更強。但這種方案只是階段性的,還存在一些問題。首先,載入過程中,頻繁使用到反射,會產生效能問題。其次,對於每個Activity的別名,需要進行統一維護,增加了協作成本。還有待優化。

當然,市面上有許多流行的Router方案(如阿里的ARouter),這裡只是介紹了一個思路,有好的建議歡迎交流,一起進步。

上面是我整理給大家的,希望今後對大家有幫助。

相關文章:

有關Material在Angular2中的使用(詳細教學)

在Angular中使用Lodash方法具體該怎麼做?

vue-router專案實戰(詳細教學)

#在js中如何實作控製檔案拖曳並取得拖曳內容功能

以上是如何解決Router跨模組跳轉問題的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn