设计一种需要登录后跳转到目标Activity的方案

前言


在日常开发中,遇到需要登录后才能跳转的目标页面时,大多数写法如下:

if(登录校验逻辑) {
   已登录,跳转至目标页。
} else {
   未登录或登录过期时,跳转至登录页面。
}  

针对未登录或登录过期时,跳转到登录页面进行登录,登录完成后要么发送一条广播,要么借助一些主流的三方框架(如:RxJava, EventBus等)来通知登录状态,获取到登录状态后跳转到目标页面,这种写法看似简单,但写的多了,就变得冗余了,自定义一个RouteHelper来优化这种跳转流程。

场景流程图

在这里插入图片描述

定义一个Intent包装类

Activity与Activity之间跳转时,根据业务需求往往都会传递一些数据,这些数据通过Bundle来存储。,定义一个RouteMeta对象,用来收集跳转到目标页时所需信息。

public class RouteMeta extends ContextWrapper {

    private final Bundle bundle;
    private final Class<?> destination;

    private boolean isNeedAuth = false;

    // 认证类型,AuthMode
    public static final String EXTRA_AUTH_MODE = "auth_mode";
    // 在打开某个页面时,如果需要登录,此时账户为退登状态,先打开登陆页面,登录成功后再跳转目标页面。
    static final String AFTER_AUTH_JUMP_TO_TARGET_PAGE = "jump_to_target_page";

    public RouteMeta(@NonNull Context base, @NonNull Class<?> destination) {
        this(base, destination, null);
    }

    public RouteMeta(@NonNull Context base, @NonNull Class<?> destination, @Nullable Bundle extras) {
        super(base);
        this.destination = destination;
        this.bundle = (null == extras ? new Bundle() : extras);
    }

    public Class<?> getDestination() {
        return destination;
    }

    public Bundle getBundle() {
        return bundle;
    }

    /**
     * 是否需要登录
     * @param isNeedAuth true:需要登录,false:不需要登录
     * @return current
     */
    public RouteMeta setNeedAuth(boolean isNeedAuth) {
        this.isNeedAuth = isNeedAuth;
        return this;
    }

    public boolean isNeedAuth() {
        return isNeedAuth;
    }

    /**
     * @param key   a String, or null
     * @param value a String, or null
     * @return current
     */
    public RouteMeta withString(@Nullable String key, @Nullable String value) {
        bundle.putString(key, value);
        return this;
    }

    /**
     * @param key   a String, or null
     * @param value a boolean
     * @return current
     */
    public RouteMeta withBoolean(@Nullable String key, boolean value) {
        bundle.putBoolean(key, value);
        return this;
    }

    /**
     * @param key   a String, or null
     * @param value a short
     * @return current
     */
    public RouteMeta withShort(@Nullable String key, short value) {
        bundle.putShort(key, value);
        return this;
    }

    /**
     * @param key   a String, or null
     * @param value an int
     * @return current
     */
    public RouteMeta withInt(@Nullable String key, int value) {
        bundle.putInt(key, value);
        return this;
    }

    /**
     * @param key   a String, or null
     * @param value a long
     * @return current
     */
    public RouteMeta withLong(@Nullable String key, long value) {
        bundle.putLong(key, value);
        return this;
    }

    /**
     * @param key   a String, or null
     * @param value a double
     * @return current
     */
    public RouteMeta withDouble(@Nullable String key, double value) {
        bundle.putDouble(key, value);
        return this;
    }

    /**
     * @param key   a String, or null
     * @param value a byte
     * @return current
     */
    public RouteMeta withByte(@Nullable String key, byte value) {
        bundle.putByte(key, value);
        return this;
    }

    /**
     * @param key   a String, or null
     * @param value a char
     * @return current
     */
    public RouteMeta withChar(@Nullable String key, char value) {
        bundle.putChar(key, value);
        return this;
    }

    /**
     * @param key   a String, or null
     * @param value a float
     * @return current
     */
    public RouteMeta withFloat(@Nullable String key, float value) {
        bundle.putFloat(key, value);
        return this;
    }

    /**
     * @param key   a String, or null
     * @param value a CharSequence, or null
     * @return current
     */
    public RouteMeta withCharSequence(@Nullable String key, @Nullable CharSequence value) {
        bundle.putCharSequence(key, value);
        return this;
    }

    /**
     * @param key   a String, or null
     * @param value a Parcelable object, or null
     * @return current
     */
    public RouteMeta withParcelable(@Nullable String key, @Nullable Parcelable value) {
        bundle.putParcelable(key, value);
        return this;
    }

    /**
     * @param key   a String, or null
     * @param value an array of Parcelable objects, or null
     * @return current
     */
    public RouteMeta withParcelableArray(@Nullable String key, @Nullable Parcelable[] value) {
        bundle.putParcelableArray(key, value);
        return this;
    }

    /**
     * @param key   a String, or null
     * @param value an ArrayList of Parcelable objects, or null
     * @return current
     */
    public RouteMeta withParcelableArrayList(@Nullable String key, @Nullable ArrayList<? extends Parcelable> value) {
        bundle.putParcelableArrayList(key, value);
        return this;
    }

    /**
     * @param key   a String, or null
     * @param value a SparseArray of Parcelable objects, or null
     * @return current
     */
    public RouteMeta withSparseParcelableArray(@Nullable String key, @Nullable SparseArray<? extends Parcelable> value) {
        bundle.putSparseParcelableArray(key, value);
        return this;
    }

    /**
     * @param key   a String, or null
     * @param value an ArrayList object, or null
     * @return current
     */
    public RouteMeta withIntegerArrayList(@Nullable String key, @Nullable ArrayList<Integer> value) {
        bundle.putIntegerArrayList(key, value);
        return this;
    }

    /**
     * @param key   a String, or null
     * @param value an ArrayList object, or null
     * @return current
     */
    public RouteMeta withStringArrayList(@Nullable String key, @Nullable ArrayList<String> value) {
        bundle.putStringArrayList(key, value);
        return this;
    }

    /**
     * @param key   a String, or null
     * @param value an ArrayList object, or null
     * @return current
     */
    public RouteMeta withCharSequenceArrayList(@Nullable String key, @Nullable ArrayList<CharSequence> value) {
        bundle.putCharSequenceArrayList(key, value);
        return this;
    }

    /**
     * @param key   a String, or null
     * @param value a Serializable object, or null
     * @return current
     */
    public RouteMeta withSerializable(@Nullable String key, @Nullable Serializable value) {
        bundle.putSerializable(key, value);
        return this;
    }

    /**
     * @param key   a String, or null
     * @param value a byte array object, or null
     * @return current
     */
    public RouteMeta withByteArray(@Nullable String key, @Nullable byte[] value) {
        bundle.putByteArray(key, value);
        return this;
    }

    /**
     * @param key   a String, or null
     * @param value a short array object, or null
     * @return current
     */
    public RouteMeta withShortArray(@Nullable String key, @Nullable short[] value) {
        bundle.putShortArray(key, value);
        return this;
    }

    /**
     * @param key   a String, or null
     * @param value a char array object, or null
     * @return current
     */
    public RouteMeta withCharArray(@Nullable String key, @Nullable char[] value) {
        bundle.putCharArray(key, value);
        return this;
    }

    /**
     * @param key   a String, or null
     * @param value a float array object, or null
     * @return current
     */
    public RouteMeta withFloatArray(@Nullable String key, @Nullable float[] value) {
        bundle.putFloatArray(key, value);
        return this;
    }

    /**
     * @param key   a String, or null
     * @param value a CharSequence array object, or null
     * @return current
     */
    public RouteMeta withCharSequenceArray(@Nullable String key, @Nullable CharSequence[] value) {
        bundle.putCharSequenceArray(key, value);
        return this;
    }

    /**
     * @param key   a String, or null
     * @param value a Bundle object, or null
     * @return current
     */
    public RouteMeta withBundle(@Nullable String key, @Nullable Bundle value) {
        bundle.putBundle(key, value);
        return this;
    }

    /**
     * 导航到目标页。
     */
    public void navigation() {
        // 1、无需登录,直接打开页面。
        if (!isNeedAuth()) {
            Intent intent = new Intent(this, getDestination());
            if (getBundle() != null) intent.putExtras(getBundle());
            startActivity(intent);
            return;
        }
        // 2、需要登录,Token有效,直接登录。
        if (AccountHelper.getDefault().isAuthToken()) {
            Intent intent = new Intent(this, getDestination());
            if (getBundle() != null) intent.putExtras(getBundle());
            startActivity(intent);
            return;
        }
        // 3、需要登录,Token无效跳转到登录页面。
        Intent intent = new Intent(this, RouteHelper.getDefault().getAuthPage());
        intent.putExtra(EXTRA_AUTH_MODE, AuthMode.PHONE_LOGIN.name());
        intent.putExtra(AFTER_AUTH_JUMP_TO_TARGET_PAGE, getDestination().getCanonicalName());
        if (getBundle() != null) intent.putExtras(getBundle());
        startActivity(intent);
    }
}

Tips:
AccountHelper为数据存储类,存储Token及登录信息相关,可根据自身项目需求修改AccountHelper调用处代码。
AuthMode认证类型,我的项目存在多种登录方式,这里是定义的一个枚举类,这个根据自身项目业务调整。

RouteHelper

在RouteHelper中向外暴漏相关API。

public class RouteHelper {

    // 设置一个Auth页面,当需要认证时跳转至该页面。
    private Class<?> authPage;

    private volatile static RouteHelper helper = null;

    private RouteHelper() {}

    public static RouteHelper getDefault() {
        if (helper == null) {
            synchronized (RouteHelper.class) {
                if (helper == null) {
                    helper = new RouteHelper();
                }
            }
        }
        return helper;
    }

    public void init(@NonNull IRouteAuthPage iRoutePage) {
        this.authPage = iRoutePage.createAuth();
    }

    Class<?> getAuthPage() {
        return authPage;
    }

    /**
     * 跳转Activity
     * @param tClass 目标Activity
     */
    public RouteMeta with(@NonNull Context context, @NonNull Class<?> tClass) {
        if (authPage == null) throw new NullPointerException("RouteHelper未初始化~");
        return new RouteMeta(context, tClass);
    }

    /**
     * 跳转Activity
     * @param tClass 目标Activity
     * @param extras 跳转Activity时携带的Bundle对象。
     */
    public RouteMeta with(@NonNull Context context, @NonNull Class<?> tClass, @Nullable Bundle extras) {
        if (authPage == null) throw new NullPointerException("RouteHelper未初始化~");
        return new RouteMeta(context, tClass, extras);
    }

    /**
     * 跳转到认证页面
     */
    public void withAuth(@NonNull Context context) {
        withAuth(context, AuthMode.PHONE_LOGIN);
    }

    /**
     * 跳转到认证页面,{@link AuthMode} 认证类型
     */
    public void withAuth(@NonNull Context context, @NonNull AuthMode mode) {
        if (authPage == null) throw new NullPointerException("RouteHelper未初始化~");
        Intent intent = new Intent(context, authPage);
        intent.putExtra(RouteMeta.EXTRA_AUTH_MODE, mode.name());
        context.startActivity(intent);
    }

    /**
     * 登录逻辑完成后调用
     */
    public void authComplete(@Nullable Activity activity) {
        if (activity == null) return;
        Bundle bundle = activity.getIntent().getExtras();
        String targetPage = bundle != null ? bundle.getString(RouteMeta.AFTER_AUTH_JUMP_TO_TARGET_PAGE) : "";
        if (targetPage != null && !targetPage.isEmpty()) {
            try {
                bundle.remove(RouteMeta.AFTER_AUTH_JUMP_TO_TARGET_PAGE);
                Class<?> tClass = Class.forName(targetPage);
                activity.startActivity(new Intent(activity, tClass).putExtras(bundle));
                activity.overridePendingTransition(0, 0);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        activity.finish();
    }
}

自定义接口

自定义一个接口,返回一个Class,初始化RouteHelper时设置登录Activity。

public interface IRouteAuthPage {

    Class<?> createAuth();
}

RouteHelper使用

  • 初始化并指定登录Activity
public class AppContext extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        // 初始化页面路由并指定认证Activity
        RouteHelper.getDefault().init(() -> AuthActivity.class);
    }
}
  • 在登录完成后调用如下代码,确保自动跳转到目标页
RouteHelper.getDefault().authComplete(this);
  • 普通跳转
RouteHelper.getDefault().with(this, GoodsDetailActivity.class)
        .withString("test", "商品详情") // 向目标页传递参数
        .navigation();
  • 打开目标页需要登录
RouteHelper.getDefault().with(this, OrderDetailActivity.class)
        .setNeedAuth(true) // 该参数标记是否需要登录
        .withString("test", "订单详情") // 向目标页传递参数
        .navigation();
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

蒙同學

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值