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,可以知道是一个列表内的点击事件,这个列表实际上就是”城市列表”,我们的场景是,点击城市列表中的城市就去旅行。所以具体到一行代码就是:
//找到旅游服务
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.一点扩展
大致使用就讨论到这里了,另外细心的朋友可能会看见我有的服务内是具有判断条件参数的,这个参数有什么作用呢?
思考这么一个场景,假设一个服务内执行的逻辑是根据前置条件而决定的,那么为了定义这么一个灵活的服务,我们就必须对其进行穿参判断。
好了,本文就到此结束,有什么问题直接留言指出,欢迎批评指正。