alibaba-ARouter(2)—ARouter IProvider 跨moudle的服务调用

IProvider

它首先是Arouter包下的一个类文件:


package com.alibaba.android.arouter.facade.template;

import android.content.Context;

/**
 * Provider interface, base of other interface.
 *
 * @author Alex <a href="mailto:[email protected]">Contact me.</a>
 * @version 1.0
 * @since 16/8/23 23:08
 */
public interface IProvider {

    /**
     * Do your init work in this method, it well be call when processor has been load.
     *
     * @param context ctx
     */
    void init(Context context);
}

看上去显得很无聊的呐。啥东东都木有的呐。

那么这个东西究竟是个啥呢?

我理解为它是ARouter内的一个概念,是ARouter提供的一种代表项目具体业务的编码和封装的范式,和android本身技术点无关,它是ARrouter所衍生出来的一种思想,可以理解为”业务的抽象与封装”的一种编程范式,它不是必要的,但它是重要的,它为我们在配合Arouter框架下进行业务封装时提供了一种“优雅的姿势”。在编码过程中,我更倾向于将其命名为IxxxService。

一个最简单的例子


import android.app.Activity;

import com.alibaba.android.arouter.facade.template.IProvider;
import com.chad.library.adapter.base.BaseQuickAdapter;

/**
 * Created by thinkpad on 2018/1/29.
 * 旅游服务
 */

public interface ITravelService extends IProvider{

    /**
     * 选择国家
     */
    void choiceCountry(Activity activity);


    /**
     * 选择城市
     */
    void choiceCity(Activity activity, BaseQuickAdapter adapter, int position);


    /**
     * 执行旅游
     */
    void doneTravle(Activity activity, BaseQuickAdapter adapter,int position,String action);
}

这样我们就定义好了一个“旅游的服务”,它内部包含3个业务,[选择国家],[选择城市],[去旅游]。

那么我们就来一次愉快的旅游吧

讨论之前我们需要知道一个场景,否则我们讨论是空洞的,无趣的,脱离了高级趣味的。
比如这么个场景,选择了国家,然后列出该国家的城市,点击城市的时候,我们去旅行。

快拿我的(灰烬使者)代码过来

界面我就不写了,本文主要讨论思想。

1.定义业务抽象接口

public interface ITravelService extends IProvider{

    /**
     * 选择国家
     */
    void choiceCountry(Activity activity);


    /**
     * 选择城市
     */
    void choiceCity(Activity activity, BaseQuickAdapter adapter, int position);


    /**
     * 执行旅游
     */
    void doneTravle(Activity activity, BaseQuickAdapter adapter,int position,String action);
}

注意,在你具体些的时候,可能会思考一个问题,这个抽象接口该往哪儿放?我的建议是放在公共域内,一般是往base里放,因为只有这样,你其他的moudle才可以对该服务进行访问。

另外,更高级一点的场景是,顶层抽象出来的接口,你不同Moudle可以有不同的实现。

2.定义业务接口实现类

@Route(path = ServicePathTag.Service_TestB_Travel)
public class ImplTestBTravelService implements ITravelService {

    @Override
    public void choiceCountry(Activity activity) {
        ARouter.getInstance().build("/testb/deeplistactivity1").navigation(activity);
//        ARouter.getInstance().build("/manage/test").navigation(activity);
    }

    @Override
    public void choiceCity(Activity activity, BaseQuickAdapter adapter, int position) {
        String country = (String) adapter.getData().get(position);
        TravelEvent travelEvent = new TravelEvent(ActivityForResultCode.CODE_DEPP_LIST_CHOICE_COUNTRY);
        travelEvent.setData(country);
        EventBus.getDefault().post(travelEvent);
        ARouter.getInstance().build("/testb/deeplistactivity2").withString("gj", (String) adapter.getData().get(position)).navigation(activity, ActivityForResultCode.CODE_DEPP_LIST_CHOICE_CITY_AND_TRAVLE_DONE);
        activity.finish();
    }

    @Override
    public void doneTravle(Activity activity, BaseQuickAdapter adapter, int position, String action) {
        String result = (String) adapter.getData().get(position);
//        Intent it = new Intent();
//        it.putExtra("data", result);
//        activity.setResult(ActivityForResultCode.CODE_DEPP_LIST_CHOICE_CITY_AND_TRAVLE_DONE, it);


        switch (action){
            case ServicePathTag.Service_TestB_Travel:
                TravelEvent travelEvent = new TravelEvent(ActivityForResultCode.CODE_DEPP_LIST_CHOICE_CITY_AND_TRAVLE_DONE);
                travelEvent.setData(result);
                EventBus.getDefault().post(travelEvent);
                activity.finish();
                break;
            case ServicePathTag.Service_TestB_FindService:
                ARouter.getInstance().build("/manage/test").navigation(activity);
                break;
        }
    }

    @Override
    public void init(Context context) {

    }
}

需要注意的是,看代码顶部有一个Path,是的,Arouter要求我们定义服务的时候也要想定义组件一样的指定一个路径。这样其他模块想调取这个服务的时候,只需要知道路径即可,具体逻辑完全不用管。

可以看到我实现了这几个方法。到这一步,“定义”这件事算是做完了,那么我接下来看调用。

3.调用

level2Adapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
        @Override
        public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
            //执行旅游
            ITravelService iTravelService = RouteServiceManager.provide(ImplTestBTravelService.class, ServicePathTag.Service_TestB_Travel);
            iTravelService.doneTravle(ChooseCityActivity.this, adapter, position, currAction);
        }
    });

这个我简单说下,看局部代码onItemClick,可以知道是一个列表内的点击事件,这个列表实际上就是”城市列表”,我们的场景是,点击城市列表中的城市就去旅行。所以具体到一行代码就是:

扫描二维码关注公众号,回复: 920076 查看本文章
//找到旅游服务
ITravelService iTravelService = RouteServiceManager.provide(ImplTestBTravelService.class, ServicePathTag.Service_TestB_Travel);

//执行旅游
iTravelService.doneTravle(ChooseCityActivity.this, adapter, position, currAction);

这里可以看到一个强转:
引用类型是,ITravelService。而并非是具体的实现类,又由于根据Path去找,那么它找到实现类必定又是精准的。这么做一个好处就是够抽象,解耦。

另外这里的 RouteServiceManager.provide 是我自己封装的一个类。其真实逻辑实际上是取“找到服务”,里面提供了俩种找到服务的方式,这里我不展开了,稍微查一下应该就知道。

public class RouteServiceManager {

    private static final String TAG = "RouteServiceManager";

    public static <T extends IProvider> T provide(Class<T> clz, String path) {

        if (TextUtils.isEmpty(path)) {
            return null;
        }

        IProvider provider = null;

        try {
            provider = (IProvider) ARouter.getInstance()
                    .build(path)
                    .navigation();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


        return (T) provider;
    }

    public static <T extends IProvider> T provide(Class<T> clz) {

        IProvider provider = null;
        try {
            provider = ARouter.getInstance().navigation(clz);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return (T) provider;
    }


    /**
     * 获取用户名字的服务
     *
     * @param userId
     * @return
     */
    public static String getUserName(String userId) {

        IUserInfoService userInfoModuleService = null;

        //方式1:模块间通过类名称发现服务
        userInfoModuleService = ARouter.getInstance().navigation(IUserInfoService.class);

        //方式2:模块间通过路径名称发现服务
        userInfoModuleService = (IUserInfoService) ARouter.getInstance()
                .build(ServicePathTag.Service_UserInfo)
                .navigation();

        if (userInfoModuleService != null) {
            return userInfoModuleService.getUserName(userId);
        }

        return "";
    }


}

4.一点扩展

大致使用就讨论到这里了,另外细心的朋友可能会看见我有的服务内是具有判断条件参数的,这个参数有什么作用呢?
思考这么一个场景,假设一个服务内执行的逻辑是根据前置条件而决定的,那么为了定义这么一个灵活的服务,我们就必须对其进行穿参判断。
好了,本文就到此结束,有什么问题直接留言指出,欢迎批评指正。

猜你喜欢

转载自blog.csdn.net/user11223344abc/article/details/79913830