当前位置 : 主页 > 手机开发 > android >

Android基于方法池与回调实现登录拦截的场景

来源:互联网 收集:自由互联 发布时间:2023-02-01
目录 前言 一、使用通知与回调 二、使用方法池 总结 前言 前面的文章我们讲到APP登录拦截的功能实现,现在网上比较多的推荐使用AOP,我们使用下来还是太麻烦,兼容性问题很多,(
目录
  • 前言
  • 一、使用通知与回调
  • 二、使用方法池
  • 总结

前言

前面的文章我们讲到APP登录拦截的功能实现,现在网上比较多的推荐使用AOP,我们使用下来还是太麻烦,兼容性问题很多,(坑太多,项目我已经改回来了,如果想体验AOP可以切换aop分支运行)

难道就想实现一个这么简单的功能,就非得使用AOP了吗?有没有简单一点的方式,方式其实太多了,个人感觉的话,完全没必要为了这么个小功能导入一个AOP库。今天我们看看使用方法池与通知回调的方式来处理登录拦截的逻辑。

一、使用通知与回调

其实本质逻辑就是想判断用户是否已经登录,然后跳转到登录页面,登录完成之后再跳转到个人中心,那我们使用通知回调不就行了吗?

在登录完成之后发出通知,在首页我们接受这个通知就调用去个人中心的方法不就行了吗?

使用通知的方式有很多,这里我们以LiveEventBus为例:

public class FunctionManager {
    private static FunctionManager functionManager;
    private static HashMap<String, Function> mFunctionMap;
    public FunctionManager() {
        mFunctionMap = new HashMap<>();
    }
    public static FunctionManager get() {
        if (functionManager == null) {
            functionManager = new FunctionManager();
        }
        return functionManager;
    }
    public void addLoginCallback(LifecycleOwner owner, ILoginCallback callback) {
        LiveEventBus.get("login", Boolean.class).observe(owner, aBoolean -> {
            if (aBoolean != null && aBoolean) {
                callback.callback();
            }
        });
    }
    public interface ILoginCallback {
        void callback();
    }
    public void finishLogin() {
        LiveEventBus.get("login").post(true);
    }
}

我们封装一个发送事件和一个接收事件,注意使用的时候添加回调的方法不要放在点击事件中。否则多次点击会重复调用的。

    override fun startObserve() {
        FunctionManager.get().addLoginCallback(this) {
            gotoProfilePage()
        }
    }
    override fun init() {
        mBtnCleanToken.click {
            SP().remove(Constants.KEY_TOKEN)
            toast("清除成功")
        }
        mBtnProfile.click {
            checkLogin()
        }
    }
    private fun checkLogin() {
        if (SP().getString(Constants.KEY_TOKEN, "").checkEmpty()) {
            gotoLoginPage()
        } else {
            gotoProfilePage()
        }
    }
    private fun gotoLoginPage() {
        gotoActivity&lt;LoginDemoActivity&gt;()
    }
    private fun gotoProfilePage() {
        gotoActivity&lt;ProfileDemoActivity&gt;()
    }

效果:

二、使用方法池

上面一种方法依赖于LiveData,我们都知道LiveData的值在一些特性情况下并不保险,当然我们可以使用FlowBus来缓解这一问题(只能在Kotlin项目中使用了),并且还存在使用不当,导致多次订阅,就会发生执行N此的逻辑。就需要我们再添加回调的方法中自己判断去重的逻辑。如果大家有兴趣也可以自行扩展,并不复杂

我们还可以使用另一种方便的方式,支持 Java 和 Kotlin ,我们使用方法池把需要执行的方法放入缓存中,当我们登录成功之后再把缓存中的方法拿出来执行,可以灵活放入多个方法。

定义方法对象

public abstract class IFunction {
    public String functionName;
    public IFunction(String functionName) {
        this.functionName = functionName;
    }
    protected abstract void function();
}

方法管理类

public class FunctionManager {
    private static FunctionManager functionManager;
    private static HashMap<String, IFunction> mFunctionMap;
    public FunctionManager() {
        mFunctionMap = new HashMap<>();
    }
    public static FunctionManager get() {
        if (functionManager == null) {
            functionManager = new FunctionManager();
        }
        return functionManager;
    }
    /**
     * 添加方法
     */
    public FunctionManager addFunction(IFunction function) {
        if (mFunctionMap != null) {
            mFunctionMap.put(function.functionName, function);
        }
        return this;
    }
    /**
     * 执行方法
     */
    public void invokeFunction(String key) {
        if (TextUtils.isEmpty(key)) {
            return;
        }
        if (mFunctionMap != null) {
            IFunction function = mFunctionMap.get(key);
            if (function != null) {
                function.function();
                //用完移除掉
                removeFunction(key);
            } else {
                try {
                    throw new RuntimeException("function not found");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
    /**
     * 使用之后移除相关的缓存
     */
    public void removeFunction(String key) {
        if (mFunctionMap != null) {
            mFunctionMap.remove(key);
        }
    }
}

使用:

 override fun init() {
        mBtnCleanToken.click {
            SP().remove(Constants.KEY_TOKEN)
            toast("清除成功")
        }
        mBtnProfile.click {
            checkLogin()
        }
    }
    private fun checkLogin() {
        if (SP().getString(Constants.KEY_TOKEN, "").checkEmpty()) {
            FunctionManager.get().addFunction(object : IFunction("gotoProfilePage") {
                override fun function() {
                    gotoProfilePage()
                }
            })
            gotoLoginPage()
        } else {
            gotoProfilePage()
        }
    }
    private fun gotoLoginPage() {
        gotoActivity<LoginDemoActivity>()
    }
    private fun gotoProfilePage() {
        gotoActivity<ProfileDemoActivity>()
    }

我这里是为了兼容其他的场景使用,需要传入方法的key,如果大家只想用于拦截登录这一个场景,大家可以把Key的值固定化。

记得在LoginActivity中登录成功的时候回调处理

    fun doLogin() {
        showStateLoading()
        CommUtils.getHandler().postDelayed({
            showStateSuccess()
            SP().putString(Constants.KEY_TOKEN, "abc")
            finish()
            //方法池的方式
             FunctionManager.get().invokeFunction("gotoProfilePage")
            }, 500)
        }

效果和使用通知的效果一致

总结

不使用AOP我们一样能完成登录拦截的功能,思路不同但是实现的效果是相同的,使用原生的库或一些特性我们就无需再导入一个不好控制的库。

之前我们说过AOP框架的一些缺点,比如影响性能,编译慢,安装包体积大,Kotlin不友好,APG不友好等等,

那么这样使用方法池或者回调的方式有什么优缺点呢?

  • 优点:轻量,不影响性能,内存开销小,支持Kotlin、Java。
  • 缺点:相对使用没有AOP那么简便,判断是否登录的逻辑得自己写了。

当然了这种工具类管理的方式只是一种思路,实现的方法有很多,我这里只是举例两种用的比较多的方式回调与方法池,如果大家对此思路有优化的地方也可以评论区交流。

后期我会再出一些拦截登录的其他思路,比如基于Intent,基于线程池,基于协程等等,大家可以对比一下 AOP,方法池和其他一些实现思路,哪一种比较好。

以上就是Android基于方法池与回调实现登录拦截的场景的详细内容,更多关于Android登录拦截的资料请关注自由互联其它相关文章!

上一篇:KotlinFlow常用封装类StateFlow使用详解
下一篇:没有了
网友评论