Android基于方法池與回調(diào)實(shí)現(xiàn)登錄攔截的場(chǎng)景
前言
前面的文章我們講到APP登錄攔截的功能實(shí)現(xiàn),現(xiàn)在網(wǎng)上比較多的推薦使用AOP,我們使用下來(lái)還是太麻煩,兼容性問(wèn)題很多,(坑太多,項(xiàng)目我已經(jīng)改回來(lái)了,如果想體驗(yàn)AOP可以切換aop分支運(yùn)行)
難道就想實(shí)現(xiàn)一個(gè)這么簡(jiǎn)單的功能,就非得使用AOP了嗎?有沒(méi)有簡(jiǎn)單一點(diǎn)的方式,方式其實(shí)太多了,個(gè)人感覺(jué)的話,完全沒(méi)必要為了這么個(gè)小功能導(dǎo)入一個(gè)AOP庫(kù)。今天我們看看使用方法池與通知回調(diào)的方式來(lái)處理登錄攔截的邏輯。
一、使用通知與回調(diào)
其實(shí)本質(zhì)邏輯就是想判斷用戶是否已經(jīng)登錄,然后跳轉(zhuǎn)到登錄頁(yè)面,登錄完成之后再跳轉(zhuǎn)到個(gè)人中心,那我們使用通知回調(diào)不就行了嗎?
在登錄完成之后發(fā)出通知,在首頁(yè)我們接受這個(gè)通知就調(diào)用去個(gè)人中心的方法不就行了嗎?
使用通知的方式有很多,這里我們以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);
}
}
我們封裝一個(gè)發(fā)送事件和一個(gè)接收事件,注意使用的時(shí)候添加回調(diào)的方法不要放在點(diǎn)擊事件中。否則多次點(diǎn)擊會(huì)重復(fù)調(diào)用的。
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<LoginDemoActivity>()
}
private fun gotoProfilePage() {
gotoActivity<ProfileDemoActivity>()
}
效果:

二、使用方法池
上面一種方法依賴于LiveData,我們都知道LiveData的值在一些特性情況下并不保險(xiǎn),當(dāng)然我們可以使用FlowBus來(lái)緩解這一問(wèn)題(只能在Kotlin項(xiàng)目中使用了),并且還存在使用不當(dāng),導(dǎo)致多次訂閱,就會(huì)發(fā)生執(zhí)行N此的邏輯。就需要我們?cè)偬砑踊卣{(diào)的方法中自己判斷去重的邏輯。如果大家有興趣也可以自行擴(kuò)展,并不復(fù)雜
我們還可以使用另一種方便的方式,支持 Java 和 Kotlin ,我們使用方法池把需要執(zhí)行的方法放入緩存中,當(dāng)我們登錄成功之后再把緩存中的方法拿出來(lái)執(zhí)行,可以靈活放入多個(gè)方法。
定義方法對(duì)象
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;
}
/**
* 執(zhí)行方法
*/
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();
}
}
}
}
/**
* 使用之后移除相關(guān)的緩存
*/
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>()
}
我這里是為了兼容其他的場(chǎng)景使用,需要傳入方法的key,如果大家只想用于攔截登錄這一個(gè)場(chǎng)景,大家可以把Key的值固定化。
記得在LoginActivity中登錄成功的時(shí)候回調(diào)處理
fun doLogin() {
showStateLoading()
CommUtils.getHandler().postDelayed({
showStateSuccess()
SP().putString(Constants.KEY_TOKEN, "abc")
finish()
//方法池的方式
FunctionManager.get().invokeFunction("gotoProfilePage")
}, 500)
}
效果和使用通知的效果一致

總結(jié)
不使用AOP我們一樣能完成登錄攔截的功能,思路不同但是實(shí)現(xiàn)的效果是相同的,使用原生的庫(kù)或一些特性我們就無(wú)需再導(dǎo)入一個(gè)不好控制的庫(kù)。
之前我們說(shuō)過(guò)AOP框架的一些缺點(diǎn),比如影響性能,編譯慢,安裝包體積大,Kotlin不友好,APG不友好等等,
那么這樣使用方法池或者回調(diào)的方式有什么優(yōu)缺點(diǎn)呢?
- 優(yōu)點(diǎn):輕量,不影響性能,內(nèi)存開(kāi)銷小,支持Kotlin、Java。
- 缺點(diǎn):相對(duì)使用沒(méi)有AOP那么簡(jiǎn)便,判斷是否登錄的邏輯得自己寫(xiě)了。
當(dāng)然了這種工具類管理的方式只是一種思路,實(shí)現(xiàn)的方法有很多,我這里只是舉例兩種用的比較多的方式回調(diào)與方法池,如果大家對(duì)此思路有優(yōu)化的地方也可以評(píng)論區(qū)交流。
后期我會(huì)再出一些攔截登錄的其他思路,比如基于Intent,基于線程池,基于協(xié)程等等,大家可以對(duì)比一下 AOP,方法池和其他一些實(shí)現(xiàn)思路,哪一種比較好。
以上就是Android基于方法池與回調(diào)實(shí)現(xiàn)登錄攔截的場(chǎng)景的詳細(xì)內(nèi)容,更多關(guān)于Android登錄攔截的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
OpenGL Shader實(shí)例分析(3)等待標(biāo)識(shí)效果
這篇文章主要介紹了OpenGL Shader實(shí)例分析第3篇,等待標(biāo)識(shí)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-02-02
Android實(shí)現(xiàn)簡(jiǎn)單下拉篩選框
這篇文章主要為大家詳細(xì)介紹了一款簡(jiǎn)單靈活的Android下拉篩選框,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-10-10
Android實(shí)現(xiàn)RecyclerView添加分割線的簡(jiǎn)便方法
這篇文章主要介紹了Android實(shí)現(xiàn)RecyclerView添加分割線的簡(jiǎn)便方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07
Android開(kāi)發(fā)中使用Intent打開(kāi)第三方應(yīng)用及驗(yàn)證可用性的方法詳解
這篇文章主要介紹了Android開(kāi)發(fā)中使用Intent打開(kāi)第三方應(yīng)用及驗(yàn)證可用性的方法,結(jié)合實(shí)例形式分析了Android使用Intent打開(kāi)第三方應(yīng)用的三種常用方式及使用注意事項(xiàng),需要的朋友可以參考下2017-11-11
Android?Studio開(kāi)發(fā)實(shí)現(xiàn)簡(jiǎn)單計(jì)算器功能
這篇文章主要為大家詳細(xì)介紹了Android?Studio開(kāi)發(fā)實(shí)現(xiàn)簡(jiǎn)單計(jì)算器功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05
Android巧用ActionBar實(shí)現(xiàn)tab導(dǎo)航效果
這篇文章主要為大家詳細(xì)介紹了Android巧用ActionBar實(shí)現(xiàn)tab導(dǎo)航效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-05-05
Android LayerDrawable超詳細(xì)講解
一個(gè)LayerDrawable是一個(gè)可以管理一組drawable對(duì)象的drawable。在LayerDrawable的drawable資源按照列表的順序繪制,所以列表的最后一個(gè)drawable繪制在最上層2022-11-11
android SectorMenuView底部導(dǎo)航扇形菜單的實(shí)現(xiàn)代碼
這篇文章主要介紹了android SectorMenuView底部導(dǎo)航扇形菜單的實(shí)現(xiàn)代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-02-02

