モジュールの下にあるページにまたがるジャンプを解決する

6557 ワード

人ができるのは、できることを信じることだ.
一、前言
モジュール化開発プロジェクトを開始した後、重要な問題はページ参照のジャンプ問題です.
モジュール化については、私のもう一つの文章Androidモジュール化開発の探求を参照してください.
プロジェクトをモジュール化して分割するだけに,各モジュール間には依存関係もなく,互いに見えないため,AモジュールのaインタフェースからBモジュールのbインタフェースにジャンプするにはどうすればよいのだろうか.
二、モジュールにまたがってジャンプする方法
ここでは、一般的なジャンプ方法について説明します.
  • ジャンプ
  • を表示
  • 暗黙ジャンプ
  • Schemeプロトコルジャンプ
  • 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を設定する.
    例:
    インベントリファイル
    
    "com.whaty.base.BaseWebViewActivity"
        android:hardwareAccelerated="true">
            
                "android.intent.category.DEFAULT" />
                "com.whaty.base.BaseWebViewActivity" />
            
    
    

    ジャンプ時:
    //        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などを設定します.
    ".ui.BbbActivity"
        
            "android.intent.category.DEFAULT" />
            "android.intent.action.VIEW" />
            "bbb"
                android:path="/home"
                android:scheme="wsc" />
        
    
    

    ジャンプ時:
    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案を紹介します.
    三、なぜルーターを使うのか
    Googleは、明示的および暗黙的な2つのオリジナルルーティングスキームを提供しています.しかし、モジュール化開発では、明示的な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();
        }
    }
    

    アプリケーションが起動すると、アプリケーションでパッケージの下のすべてのクラスをスキャンし、名前の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など)があり、ここではただ一つの考え方を紹介しただけで、良い提案があって交流を歓迎し、一緒に進歩します.
    もっと素晴らしい内容、私の微信の公衆番号--Android自動車に注目してください.