Android的简单Router实现

2019-03-18  本文已影响0人  编程_书恨少

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

上一篇 下一篇

猜你喜欢

热点阅读