1.为什么会想写Router
1.a 最近准备开始正正经经的写android的应用了,所以最近在想一些架构和结构的东西。这里最先想到的就是统一处理页面的跳转方式,这样有什么好处呢?
那我们先看一下传统的跳转传值方式
a.A跳转B页面时,如果不需要下个页面回传数据,调用方法是这样婶的
Intent intent = new Intent();
intent.setClass(this, OneActivity.class);
startActivity(intent);
b.A跳转B页面时,如果需要下个页面回传数据,调用方法是这样婶的
Snip20190318_3.png
并且需要在B页面设置resultCode值
Intent intent = new Intent();
intent.setClass(OneActivity.this, MainActivity.class);
intent.putExtra("price", 10);
setResult(1, intent);
finish();
而且还需要在A页面进行方法的监听,才能实现回传数据,天哪
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1 && resultCode == 1) {
System.out.println(data);
}
}
c.如果是A->B->C,然后C->A,进行反向传值的话,需要这样处理
真的真的是好麻烦,并且这还是在不涉及到启动模式的情况下。如果涉及到不同的启动模式还需要实现不同的回调方法,才能监听到回传的数据。真的是感觉好麻烦。如果你对启动模式还不了解的话,请先移步到这里。https://www.cnblogs.com/claireyuancy/p/7387696.html
这种处理方式,当页面会被几个页面跳回的话,处理起来就会很麻烦,只是记住每个页面的resultCode就很麻烦了,还要进行判断。想象一下,业务的判断
竟然还要根据非业务的回传值判断
好了,吐槽就到这里。那么我们来思考一个问题,如果是我们来做的话,想要以什么样的方式来进行参数的传递和参数回传的判断呢?
基于传统方式的使用不便,调用方法偏多,并且碎片化的散落在不同的位置,使得代码的可读性下降,不易于后续维护。所以我提出了以下四点需求
a.统一跳转方法
b.统一跳转方法的传参方式
c.统一回退方法
d.统一回退方法的参数处理
e.不用再关心不同启动模式下方法不同意的问题
2.解决方案
我的解决方案就是自己写一个路由,进行集中式的栈管理
a 首先,我们要有一个集中管理栈
/// 单例
public static Router getInstance() {
if (instance == null) {
instance = new Router();
}
if (activityStack == null) {
activityStack = new Stack<Activity>();
}
return instance;
}
b 统一跳转方式和回退方式
/// 向前跳转方法
public void routeForward(Class<?> cls, Map params) {
instance.params = params;
Intent intent = new Intent();
Activity currentActivity = currentActivity();
intent.setClass(currentActivity, cls);
currentActivity.startActivity(intent);
}
/// 向后跳转到指定的控制器
public void routeBack(Class<?> cls, Map params) {
BaseActivity backActivity = (BaseActivity) getActivity(cls);
if (backActivity == null) return;
backActivity.backParams = params;
for (int i = activityStack.size() - 1; i > 0; i--) {
Activity activity = activityStack.get(i);
if (activity.equals(backActivity) == false) {
finishActivity(activity);
} else {
return;
}
}
}
/// 结束指定的Activity
public void finishActivity(Activity activity) {
if (activity != null && activityStack.contains(activity)) {
activityStack.remove(activity);
activity.finish();
activity = null;
} else {
Log.e("RouterError","移除控制器失败");
}
}
c 统一传参方式
压栈参数,和回退参数,统一在基类中进行管理
public Map params;
public Map backParams;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_base);
Router.getInstance().addActivity(this);
BaseActivity currentActivity = (BaseActivity) Router.getInstance().currentActivity();
currentActivity.params = Router.getInstance().params;
}
在routeForward方法中,统一进行参数的赋值
在routeBack方法中,统一进行回退页面参数的赋值
3.解决方案演示Demo
现在回到我们之前的问题,A页面跳转B页面,再从B页面跳回A页面时,传值的问题。
1.现在基类中做好参数配置
public Map params;
public Map backParams;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_base);
Router.getInstance().addActivity(this);
BaseActivity currentActivity = (BaseActivity) Router.getInstance().currentActivity();
currentActivity.params = Router.getInstance().params;
}
2.A页面跳转B页面,统一正向传值
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Map params = new HashMap();
params.put("price", 11);
params.put("backClass", "A");
Router.getInstance().routeForward(B.class, params);
}
});
在B页面获取A页面传来的值
int price = (int) params.get("price");
3.B页面跳转A页面,统一反向传值
backBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Map backParams = new HashMap();
backParams.put("price", 30);
Router.getInstance().routeBack(A.class, backParams);
}
});
并且这个回退方法是根据Activity的类名识别的,即使是回退几个十几个页面也是同一个方法搞定。(这个回退方法可以改成让A页面传入参数String类型的类名,然后内部反射,指明会退到哪个页面,这样可以做到解耦,时间关系这里我就先不做修改了,使用的同学可以自行更改)
这时页面就会回退到A,然后只需要在A页面的onResume方法中进行统一判断就可以了
@Override
protected void onResume() {
super.onResume();
if (backParams != null) {
int price = (int) backParams.get("price");
}
System.out.println();
}
4.物理返回键处理
在基类中添加了一个设置指定返回类型和回传参数的方法,设置了该方法,则认为物理返回键需要返回到Class类对应的activity,并回传相应参数,进行页面处理
BaseActivity中添加方法
public Class backPressedCls;
/*物理返回键设置参数方法*/
public void setPhysicalBack(Class<?> cls, Map par) {
backPressedCls = cls;
backParams = par;
}
在基类中重写onBackPressed方法
@Override
public void onBackPressed() {
super.onBackPressed();
System.out.println();
if (backPressedCls != null) {
Router.getInstance().routeBack(backPressedCls, backParams);
}
}
外部使用时,提前设置好就可以了
Demo中是在TwoActivity中进行了物理键返回设置
Map params = new HashMap();
params.put("price", 13);
setPhysicalBack(OneActivity.class, params);
最后,放出Demo的github地址https://github.com/majianghai/Router_android
网友评论