企業級app組件化開發5----Arouter路由

在之前的組件化開發中,如果ModuleA想要調用另一個ModuleB中的類或者方法,只能通過添加依賴的方式,而且是強依賴;這種形式存在的一個問題就是:如果ModuleB中的類發生改變,那麼ModuleA也需要改變該類,甚至該類已經無法繼續使用了,擴展性不強,耦合性太高。

在這裏插入圖片描述

但是開源的ARouter路由就解決了這個問題,Module之間不再是處於強耦合的關係,而是使用ARouter作爲中間人,所有的Module在ARouter中註冊後,那麼其他的Module都可以調用ARouter中該Module的類和方法,而且Module在ARouter中註冊之後,不管Module中怎麼改變,其他獲取到仍然是之前的類,不會因爲其他的Module改變而需要去改變。

例如Module在ARouter註冊一個類 B.a,ModuleA調用這個類,ModuleB此後將B.a改成了B.c,那麼其他Module調用的依然是B.a,並不受ModuleB改變受到影響。

1、ARouter的基礎使用

《阿里巴巴ARouter手冊》具體使用可以從這裏獲取更多,還有源碼解析等,這裏主要講解ARouter的主要用法。

(1)依賴配置

defaultConfig以及dependencies中添加以下依賴

javaCompileOptions {
            annotationProcessorOptions {
                arguments = [moduleName: project.getName()]
            }
        }
implementation 'com.alibaba:arouter-api:1.3.1'
annotationProcessor 'com.alibaba:arouter-compiler:1.1.3'

(2)Activity之間的跳轉

在之前沒有使用ARouter的時候,使用Activity之間跳轉的方式是通過startActivity的方式,尤其是使用顯示意圖Intent跳轉的時候,耦合性太高。

在使用ARouter時,首先需要在Application中註冊初始化之後,纔可以使用

 //初始化ARouter
        if(isDebug()){
            ARouter.openLog();
            ARouter.openDebug();
        }
        ARouter.init(this);

現在就可以實現Activity之間的跳轉了,在當前Activity中,如果想要跳轉到目標Activity,只需要以下一行代碼即可。

 btn_jump.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ARouter.getInstance().build(Router.MAIN_ACTIVITY).navigation();
            }
        });

build中,代表跳轉的目標Activity,所以在目標Activity中,需要使用@Route註解來註釋。

@Route(path = Router.MAIN_ACTIVITY)
public class MainActivity extends AppCompatActivity {

    private Handler handler = new Handler();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //注入
        ARouter.getInstance().inject(this);
    }
}

一旦使用註解,那麼就需要將ARouter注入!!!

(3)Activity攜帶參數跳轉

在ARouter提供的API中,可傳遞的數據類型和Intent基本一致:基本數據類型、可序列化數據(2種)。。。

ARouter.getInstance()
       .build(Router.MAIN_ACTIVITY)
       .withString("name","ClearLove")
       .withInt("age",12)
       .navigation();

目標Activity:

@Route(path = Router.MAIN_ACTIVITY)
public class MainActivity extends AppCompatActivity {

    private TextView tv_name,tv_age;
    @Autowired(name = "name") //這裏可以不用寫,因爲攜帶的key是一致的
    String name;  // String mName;  如果這樣聲明就需要加name
    @Autowired()
    int age;


    private Handler handler = new Handler();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //注入
        ARouter.getInstance().inject(this);
        
        tv_name = findViewById(R.id.tv_name);
        tv_age = findViewById(R.id.tv_age);

        tv_name.setText(name);
        tv_age.setText(age+"");
    }
}

通過@Autowired註解來修飾,需要注意的是,如果攜帶數據的key一致,在@Autowired不需要聲明name。

(4)Uri跳轉

     Uri uri = Uri.parse(Router.MAIN_ACTIVITY);
                ARouter.getInstance()
                        .build(uri)
                        .withString("name","ClearLove")
                        .withInt("age",12)
                        .navigation();

(5)動畫

   Uri uri = Uri.parse(Router.MAIN_ACTIVITY);
                ARouter.getInstance()
                        .build(uri)
                        .withTransition(Animation.REVERSE,Animation.ZORDER_TOP)
                        .withString("name","ClearLove")
                        .withInt("age",12)
                        .navigation();

使用withTransition可以設置入場動畫和出場動畫,來設置跳轉動畫。

(6)路由回調 NavigationCallback

 				 ARouter.getInstance()
                        .build(uri)
                        .withTransition(Animation.REVERSE,Animation.ZORDER_TOP)
                        .withString("name","ClearLove")
                        .withInt("age",12)
                        .navigation(VideoActivity.this, new NavigationCallback() {
                            @Override
                            public void onFound(Postcard postcard) {
                                Log.e("TAG",postcard.getPath()+","+postcard.getGroup());
                            }

                            @Override
                            public void onLost(Postcard postcard) {

                            }

                            @Override
                            public void onArrival(Postcard postcard) {

                            }

                            @Override
                            public void onInterrupt(Postcard postcard) {

                            }
                        });

使用NavigationCallback可以完成對路由的回調,主要分爲4個方面,分別爲onFound(路由尋址成功)、onLost(路由尋址失敗)、onArrival(路由導航成功)、onInterrupt(攔截器),在四個方法中,都涉及到了一個類Postcard ,有兩個比較關鍵的屬性值,分別是path和group,path指的是路由的路徑,group指的是分組。

2020-05-31 17:37:06.335 29646-29646/com.example.glide E/TAG: /app/main_activity,app

默認情況下,group的分組爲app,也就是二級目錄/xx/xxx,第一個位置的數據。

在navigation中除了可以完成路由的回調,還可以完成帶結果的回調,也就是startActivityForResult,可以傳入requestCode來實現。

2、ARouter實現服務化

以上只是ARouter使用的一些常用方法,最關鍵的還是在組件化開發中,避免模塊間的強依賴,使用ARouter服務化進行模塊解耦,纔是組件化中的核心。

下面拉回開篇的場景:有兩個ModuleA和ModuleB,ModuleA需要使用ModuleB中的一個類,如果相互依賴組件,本來沒有關係的兩個組件變得耦合性太高;所以對於業務層的抽離,可以在lib_base組件中,創建一個服務接口,該接口可以對外暴露;該接口的具體實現類是在ModuleB中實現的,具體的實現就是ModuleA想要調用ModuleB中的部分方法;那麼當ModuleA想要調用ModuleB中類的方法時,直接依賴lib_base組件,通過ARouter路由獲取,這樣通過lib_base組件將兩個不相干的組件聯繫起來。

當前存在lib_video lib_base lib_share三個組件,lib_share想要調用lib_video中的方法,那麼首先在lib_base中創建一個接口,繼承自IProvider。

public interface VideoService extends IProvider {

    String getVideoName();
}

lib_video:

lib_video需要依賴lib_base庫,完成VideoService 的具體實現

@Route(path = "/lib_video/video_service")
public class VideoServiceImpl implements VideoService {

    @Override
    public String getVideoName() {

        Video video = new Video("唐人街探案",3);
        return video.getVideoName();
    }

    @Override
    public void init(Context context) {

    }
}

lib_share:

lib_share同樣需要依賴lib_base庫,而不需要和lib_video庫依賴。

	@Autowired(name = "/lib_video/video_service")
    VideoService mVideoService;

    private ShareSDKManager(){
        ARouter.getInstance().inject(this);
    }
    private static ShareSDKManager manager;
    public static ShareSDKManager getInstance(){
        if(manager == null){
            synchronized (ShareSDKManager.class){
                if(manager == null){
                    manager = new ShareSDKManager();
                }
            }
        }
        return manager;
    }
    
    //分享需要2類數據,參數和平臺
    public void shareData(ShareData data,PlatformShareDataListener listener){
        this.listener = listener;

		/*省略部分代碼*/
		
        String videoName = mVideoService.getVideoName();
        Log.e("TAG","name=="+videoName);
    }

組件路由服務化用法1:聲明服務注意要加上路由地址,否則找不到該實現類,通過服務接口直接調用方法實現。

方法2:通過navigation導航

//不需要再加AutoWried註解
VideoService mVideoService2;

mVideoService2 = ARouter.getInstance().navigation(VideoService.class);
        String videoName = mVideoService2.getVideoName();

方法3:通過build導航

//不需要再加AutoWried註解
VideoService mVideoService2;

mVideoService2 = (VideoService) ARouter.getInstance().build("/lib_video/video_service").navigation();
        String videoName = mVideoService2.getVideoName();

3、ARouter分組與攔截器

ARouter攔截器,有些類似於之前在OkHttp組件開發中,講到的攔截器。ARouter攔截器主要是攔截事件跳轉,先看下代碼

@Interceptor(priority = 1,name = "login_interceptor")
public class LoginInterceptor implements IInterceptor {

    @Override
    public void process(Postcard postcard, InterceptorCallback callback) {
        if(postcard.getGroup() == Router.NEED_LOGIN){
            //如果是需要登錄分組
            ARouter.getInstance().build(Router.LOGIN_ACTIVITY).navigation();
        }else{
            callback.onContinue(postcard);
        }
    }

    @Override
    public void init(Context context) {

    }
}

這是一個與登錄相關的攔截器,核心在於process,在process方法中有兩個形參,分別是Postcard 和 InterceptorCallback 。

Postcard 在之前介紹過,包含路由地址和分組Group,分組Group是可以在Route註解中聲明的,在路由導航的時候,可以在build中添加分組信息。

@Route(path = Router.MAIN_ACTIVITY,group = Router.NEED_LOGIN)
public class MainActivity extends AppCompatActivity {
ARouter.getInstance()
		//         路由地址             分組
       .build(Router.MAIN_ACTIVITY,Router.NEED_LOGIN)

當然加了分組之後,就可以通過攔截器,通過Postcard來獲取路由地址的分組,如果獲取到需要分組的信息,那麼就需要判斷登錄信息是否過期(這裏沒有做這個操作,在實際開發中是需要做的),如果沒有過期,那麼就通過InterceptorCallback執行onContinue繼續路由到對應地址,如果登錄信息過期,那麼就需要路由到登錄界面。

如果獲取到的分組信息是不需要登錄的,那麼就直接通過InterceptorCallback執行onContinue繼續路由到對應地址。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章