成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

您的位置:首頁技術(shù)文章
文章詳情頁

Android Fragment監(jiān)聽返回鍵的一種合理方式

瀏覽:66日期:2022-09-21 17:49:05

開場

以下場景為杜撰:

產(chǎn)品經(jīng)理:“小羅,這個信息發(fā)送界面,如果用戶輸入了內(nèi)容,點擊返回鍵的時候,要先詢問用戶是否保存草稿箱哈”。

小羅:“收到,這問題簡單。”

說完小羅就準備著手處理,然后卻發(fā)現(xiàn)信息編輯界面是一個Fragment,然而Fragment并沒有提供返回鍵點擊的直接處理;小羅雖菜,但是摸魚也摸了些年頭了,這問題難不倒小羅。

小羅心想,反正Activity提供了onBackPressed方法,再不濟的情況把這個操作分發(fā)到Fragment中去就好,可是對于處女座的小羅來說,在解決問題的基礎(chǔ)上,起碼代碼要寫的漂亮一點,寫的漂亮一點心里就舒服一點,心里舒服一點就...(此處內(nèi)容很長)。

小羅堅信“條條大路通羅馬”,我們不僅要到羅馬,還要風(fēng)風(fēng)光光的去,所以對于“Fragment如何監(jiān)聽返回鍵的點擊”,小羅決定下點功夫;

為什么關(guān)注的點是Fragment去監(jiān)聽返回鍵,而不是其他?其實在現(xiàn)在的開發(fā)過程中,F(xiàn)ragment的使用比重是非常大的,對于個人而言,幾乎整個工程的界面實現(xiàn)都是基于Fragment而非Activity。

一、最lowB的方式(不推薦)

這就是小羅心里的預(yù)備方案,在實在沒有辦法的時候會采用此方法,也就是前面提到的,我們可以在Activity執(zhí)行onBackPressed時,分發(fā)到Fragment中去;那我們用什么來分發(fā)呢?這個分發(fā)就好比是連接Activity和Fragment之間的一個紐帶,雙方均能夠訪問到這個對象就可以了,所以一個可以的選擇之一是使用ViewModel,當(dāng)然還可以有其他選擇,在此就不細聊了。

二、使用OnKeyListener(不推薦)

這種方式可能不常用,不容易想到這方面,所以這種方式也不推薦,簡單做個了解;

通過設(shè)置View的OnKeyListener來監(jiān)聽返回鍵的處理,此方法也沒什么大的弊端,只是要注意以下兩點:

1、如果把這個功能封裝在Fragment基類中的話,可能存在被覆蓋的問題;比如在基類中設(shè)置了OnKeyListener,而子類也需要設(shè)置OnKeyListener,此時設(shè)置的監(jiān)聽則會替換默認設(shè)置的監(jiān)聽,從而導(dǎo)致意想不到的可能,不過此問題幾乎不太可能發(fā)生。

2、需要注意這種方式將會改變返回鍵處理的順序,也就是會先處理OnKeyListener的回調(diào),再處理Activity的onBackPressed,所以要注意這個關(guān)系。

三、Jetpack提供的方式

其實對于返回鍵的分發(fā),官方已經(jīng)做了支持,在Activity中提供了一個用于分發(fā)返回鍵事件的對象,通過調(diào)用Activity的getOnBackPressedDispatcher()方法得到這個對象,由于這個對象是在比較底層的androidx.activity.ComponentActivity中提供的(AppCompatActivity->FragmentAcitivty->androidx.activity.ComponentActivity),所以在Fragment中可以直接拿到這個對象添加回調(diào);

官方資料入口

//官方使用示例 public class FormEntryFragment extends Fragment { @Override public void onAttach(@NonNull Context context) { super.onAttach(context); //定義回調(diào) OnBackPressedCallback callback = new OnBackPressedCallback( true // default to enabled ) { @Override public void handleOnBackPressed() { showAreYouSureDialog(); } }; //獲取Activity的返回鍵分發(fā)器添加回調(diào) requireActivity().getOnBackPressedDispatcher().addCallback( this, // LifecycleOwner callback); }}

簡單明了,這個事情好像到此為止了~~

但隨著深入了解,事情似乎沒有這么簡單,經(jīng)過源碼分析和資料收集,發(fā)現(xiàn)如果直接使用會存在以下弊端:

1、Fragment回調(diào)處理時,無法向上傳遞

2、回調(diào)是否可用需要主動標記,而非運行時確定

簡單說一下OnBackPressedDispatcher分發(fā)返回鍵的流程:

//官方源碼 @MainThread public void onBackPressed() { Iterator<OnBackPressedCallback> iterator = mOnBackPressedCallbacks.descendingIterator(); while (iterator.hasNext()) { OnBackPressedCallback callback = iterator.next(); if (callback.isEnabled()) { callback.handleOnBackPressed(); return; } } if (mFallbackOnBackPressed != null) { mFallbackOnBackPressed.run(); } }

當(dāng)分發(fā)返回鍵事件時,會倒序循環(huán)遍歷已經(jīng)注冊的回調(diào),如果回調(diào)isEnabled設(shè)置為true,則執(zhí)行回調(diào)的方法,分發(fā)結(jié)束;

那前面提到的弊端是怎么產(chǎn)生的呢?假如一個Activity有兩個Fragment A和B,均注冊了返回鍵點擊事件(有童鞋會說了,這種場景不太可能存在,確實,這種場景是不多,但不代表沒有,做一些了解也不是壞事),并且兩個回調(diào)的isEnabled均設(shè)置為true,那么當(dāng)分發(fā)事件時,會將事件分發(fā)給B,但是B此時并不需要處理返回鍵事件,但是B又沒有辦法再繼續(xù)將事件傳遞給A了;

“你傻啊,你B不執(zhí)行返回鍵事件,就設(shè)置isEnable為false啊”

“是啊,B不執(zhí)行事件是該設(shè)置為false,可是我怎么知道什么時候去把它設(shè)置成false?難道動態(tài)綁定判斷條件的值進行設(shè)置么?”

轉(zhuǎn)頭一想“咦,好像確實可以動態(tài)修改回調(diào)的isEnabled值呢,將回調(diào)的值跟一個LiveData綁定不就可以了么!”理是這個理,但是我不愿意做額外的工作,我不愿這么干,誰知道動態(tài)判斷條件到底有多復(fù)雜呢,難道我不可以在返回鍵點擊的時候去判斷么?

四、靈機一動,官方升級版(推薦方式)

官方的方式不是存在上面兩個弊端么,解決這兩個問題不就好了;所以結(jié)合官方OnBackPressedDispatcher和OnKeyListener兩者的優(yōu)點,創(chuàng)建了andme.arch.activity.AMBackPressedDispatcher,在保留官方原有的功能的同時,更改事件分發(fā)流程,并將返回鍵持有者一并傳入,用于解決一些更復(fù)雜一點的需求;

@MainThread fun onBackPressed(): Boolean { if (!hasRegisteredCallbacks()) return false val iterator = mOnBackPressedCallbacks.descendingIterator() while (iterator.hasNext()) { val callback = iterator.next() //判斷回調(diào)是否需要消耗事件在決定是否繼續(xù)傳遞 if (callback.handleOnBackPressed(owner)) { return true } } return false }

五、官方使用技巧版

這種方法其實是我在發(fā)布文章之后,群友提供的一種思路,說實話,非常有技巧,剛開始看到的時候眼前一亮;其核心原理是默認注冊的回調(diào)是可用的,在回調(diào)執(zhí)行中,先判斷自己是否需要執(zhí)行回調(diào),如果不需要執(zhí)行回調(diào),則將自己的isEnabled設(shè)置為false,然后再調(diào)用OnBackPressedDispatcher重新分發(fā)返回鍵事件(由于此時已將自己設(shè)置為false,此時便不會響應(yīng)回調(diào)),調(diào)用方法之后再將isEnabled設(shè)置為true,巧用了遞歸,該方式不錯的;

最開始群友提供的代碼有一丟丟瑕疵,以下為修正之后的代碼,在Fragment中定義這兩個方法,在需要綁定返回鍵監(jiān)聽的時候調(diào)用這個兩個方法之一即可(推薦調(diào)用與生命周期相關(guān)的方法);

fun addOnBackPressed(onBackPressed: () -> Boolean): OnBackPressedCallback { val callback = object : OnBackPressedCallback(true) { override fun handleOnBackPressed() { if (!onBackPressed()) { isEnabled = false requireActivity().onBackPressedDispatcher.onBackPressed() isEnabled = true } } } requireActivity().onBackPressedDispatcher.addCallback(callback) return callback } fun addOnBackPressed(owner: LifecycleOwner, onBackPressed: () -> Boolean): OnBackPressedCallback { val callback = object : OnBackPressedCallback(true) { override fun handleOnBackPressed() { if (!onBackPressed()) { isEnabled = false requireActivity().onBackPressedDispatcher.onBackPressed() isEnabled = true } } } requireActivity().onBackPressedDispatcher.addCallback(owner,callback) return callback }

但是經(jīng)過慎重思考,最終我還是沒有用這種方法,雖然這種方法在幾乎百分之八九十的情況下是沒有問題的,但是我認為可能還是有場景無法滿足;

舉個例子,一個Activity添加了一個Fragment,這個Fragment又順序添加了A和B兩個ChildFragment,那在B執(zhí)行返回處理的時候,是想回到A還是finish呢?或者是其他呢,也是就是說我們無法確定,在Fragment執(zhí)行返回鍵處理時,是否需要直接調(diào)用Activity.super.onBackPressed方法的可能。

我們永遠無法預(yù)估用戶的場景到底有多復(fù)雜,需求有多變態(tài),所以盡可能的考慮把。

總結(jié)

綜上所述,我目前還是會繼續(xù)使用第四種我寫的方案,第五種方案也推薦,畢竟在絕大部分場景中都是沒有問題的那么我們考慮第四種方案到底是否可行?

1、功能性

滿足了功能需求,并且至少目前是沒有想到有任何可能出現(xiàn)問題的場景

2、侵入性

幾乎對用戶場景沒什么影響吧,只是對用戶提供了一個可見的處理返回鍵事件的方法而已

3、替換性

如果采用第四種方案,要更換成第五種方案,容易么?一兩句代碼的事情而已

或者更換成其他方案容易么?也是一兩句代碼的的事情而已

并且即便替換成其他方案,也不會對現(xiàn)有系統(tǒng)造成任何影響,因為對于Fragment監(jiān)聽返回鍵這個需求來講,這個需求的核心就是需要一個在Fragment中處理返回鍵事件的方法而已,其他東西對用戶來講都是無感的所以總體覺得沒什么毛病;

如果你有更好的思路,歡迎溝通,不勝感激;

另外,上述功能其實并不僅僅支持在Fragment中處理返回鍵事件,理論上來說任何想要監(jiān)聽返回鍵處理的都可以通過Activity獲取AMBackPressedDispatcher對象添加回調(diào)即可。

Andme Github地址

到此這篇關(guān)于Android Fragment監(jiān)聽返回鍵的一種合理方式的文章就介紹到這了,更多相關(guān)Android Fragment監(jiān)聽返回鍵內(nèi)容請搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標簽: Android
相關(guān)文章:
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
成人免费视频免费观看| 中文字幕电影一区| 香蕉成人伊视频在线观看| 先锋影音一区二区三区| 国外精品视频| 在线视频欧美精品| 全部av―极品视觉盛宴亚洲| 国产午夜久久| 亚洲午夜在线观看视频在线| 自拍偷拍国产精品| 91丨九色丨国产丨porny| 日韩一二在线观看| 国产精一品亚洲二区在线视频| 欧美日韩不卡一区| 精品一区二区三区av| 欧美性生活一区| 天堂久久久久va久久久久| 久久久久se| 香蕉成人伊视频在线观看| 久久亚洲一区| 免费欧美在线视频| 欧美日韩免费在线视频| 国产一区视频在线看| 666欧美在线视频| 国产91精品一区二区麻豆网站| 日韩免费视频线观看| www.亚洲激情.com| 国产人成亚洲第一网站在线播放 | 成人免费视频一区二区| 日韩一区二区麻豆国产| 成人免费视频网站在线观看| 久久嫩草精品久久久精品| 欧美在线日韩精品| 最新国产成人在线观看| 一区二区高清视频| 亚洲二区在线观看| 欧美唯美清纯偷拍| 国产成人在线观看免费网站| 日韩精品在线一区二区| 91啪九色porn原创视频在线观看| 国产欧美一区二区在线观看| 韩国一区二区三区美女美女秀| 亚洲欧美日韩在线| 久久精品免费| 精品系列免费在线观看| 日韩一区二区在线观看| 91麻豆高清视频| 中文字幕日本不卡| 美日韩在线观看| 国产真实乱子伦精品视频| 精品国产精品网麻豆系列 | 精品一区二区三区在线视频| 日韩一级在线观看| 欧美一区二视频在线免费观看| 中文字幕一区二区三区精华液| 性色一区二区| 狠狠色伊人亚洲综合成人| 日韩午夜在线观看视频| 91啪亚洲精品| 一区二区不卡在线播放| 欧美日韩中字一区| 不卡电影免费在线播放一区| 中文字幕亚洲成人| 欧美中文字幕亚洲一区二区va在线| 国产成人免费视频网站| 国产精品美女一区二区在线观看| 亚洲一区三区电影在线观看| 国产一区二区网址| 国产日本一区二区| 国产精品久久久久久久免费软件 | 7777精品伊人久久久大香线蕉的 | 最新亚洲一区| 久久99国内精品| 久久亚洲一区二区三区明星换脸| 亚洲日本视频| 久草精品在线观看| 国产精品人人做人人爽人人添| 色婷婷久久久久swag精品| eeuss鲁一区二区三区| 亚洲午夜在线电影| 欧美一区二区视频观看视频| 激情六月综合| 久久国产尿小便嘘嘘| 国产丝袜欧美中文另类| 久久精品亚洲| 99久久综合99久久综合网站| 亚洲妇女屁股眼交7| 精品国产乱子伦一区| 国产精品日韩精品欧美精品| 国产99久久久久久免费看农村| |精品福利一区二区三区| 欧美在线观看视频在线| 欧美激情综合色综合啪啪| 日韩精品国产欧美| 久久精品无码一区二区三区| 噜噜爱69成人精品| 91在线免费播放| 日韩av在线发布| 久久久综合网站| 色妞www精品视频| 99re66热这里只有精品3直播| 亚欧色一区w666天堂| 欧美精品一区二区在线观看| 久久动漫亚洲| 96av麻豆蜜桃一区二区| 日韩精品成人一区二区三区| 国产欧美一区二区精品忘忧草| 91久久久免费一区二区| 欧美日韩三区| 国产精品一线二线三线| 亚洲精品高清在线| 精品国产91九色蝌蚪| 久久精品九九| 欧美黄色免费| 国内精品国产成人国产三级粉色| 亚洲精品国产品国语在线app| xnxx国产精品| 欧美日韩在线一区二区| 亚洲夫妻自拍| 99视频精品全部免费在线| 免费视频一区二区| 亚洲丝袜制服诱惑| 欧美va天堂va视频va在线| 色呦呦网站一区| 亚洲理伦在线| 欧美一区二区三区另类| 韩日精品视频一区| 午夜精品福利在线| 国产精品系列在线| 日韩一级黄色片| 在线视频你懂得一区二区三区| 亚洲精选一区| 91美女福利视频| 国产精品亚洲成人| 视频一区在线播放| 亚洲欧美日韩精品久久久久| 久久久综合视频| 日韩一卡二卡三卡四卡| 欧美在线观看你懂的| 国产精品手机在线| 午夜精品电影| av激情亚洲男人天堂| 国产一区啦啦啦在线观看| 日韩成人免费在线| 亚洲综合图片区| 亚洲色图在线播放| 国产精品网曝门| 欧美精品一区二区三区四区 | 亚洲黄一区二区三区| 欧美极品xxx| 久久亚洲精品小早川怜子| 欧美一级高清大全免费观看| 欧美曰成人黄网| 性色av一区二区怡红| 一区福利视频| 欧美精品一级| 91丨porny丨国产入口| gogogo免费视频观看亚洲一| 岛国一区二区在线观看| 国产在线观看一区二区| 久久99热这里只有精品| 日韩极品在线观看| 性久久久久久久久| 亚洲成年人网站在线观看| 亚洲图片欧美视频| 夜夜揉揉日日人人青青一国产精品| 成人欧美一区二区三区小说 | 久久看人人爽人人| 精品99一区二区三区| 日韩欧美一二三区| 4438x亚洲最大成人网| 精品视频123区在线观看| 欧美午夜免费电影| 欧美日韩亚州综合| 欧美日韩成人激情| 911精品国产一区二区在线| 欧美日韩国产123区| 欧美久久久久久蜜桃| 欧美一级夜夜爽| 91精品蜜臀在线一区尤物| 9191成人精品久久| 日韩欧美中文字幕公布| 日韩欧美激情在线| 久久综合久久综合亚洲| 久久久午夜电影| 欧美国产精品一区二区三区| 国产精品久久久久久久久搜平片| 亚洲欧洲成人自拍| 成人免费在线播放视频| 一区二区三区四区亚洲| 亚洲一区二区三区视频在线播放| 亚洲自拍偷拍图区| 性感美女极品91精品| 秋霞午夜av一区二区三区| 久久丁香综合五月国产三级网站| 国内精品伊人久久久久影院对白| 国产高清精品在线| 欧美暴力喷水在线| 亚洲美女啪啪| 久久久久国产精品一区三寸|