日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

Android Fragment監聽返回鍵的一種合理方式

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

開場

以下場景為杜撰:

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

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

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

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

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

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

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

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

二、使用OnKeyListener(不推薦)

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

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

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

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

三、Jetpack提供的方式

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

官方資料入口

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

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

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

1、Fragment回調處理時,無法向上傳遞

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

簡單說一下OnBackPressedDispatcher分發返回鍵的流程:

//官方源碼 @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(); } }

當分發返回鍵事件時,會倒序循環遍歷已經注冊的回調,如果回調isEnabled設置為true,則執行回調的方法,分發結束;

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

“你傻啊,你B不執行返回鍵事件,就設置isEnable為false啊”

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

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

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

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

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

五、官方使用技巧版

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

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

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 }

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

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

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

總結

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

1、功能性

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

2、侵入性

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

3、替換性

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

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

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

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

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

Andme Github地址

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

標簽: Android
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
亚洲丝袜啪啪| 日韩精品1区| 麻豆久久久久久| 国产亚洲午夜| 午夜久久影院| 黄色av一区| 午夜精品免费| 午夜日韩av| 日av在线不卡| 麻豆精品99| 国产精品欧美三级在线观看| 欧美精品影院| 国产精品99在线观看| 国产专区一区| 四虎成人精品一区二区免费网站| 伊人国产精品| 伊人久久成人| 日韩精品欧美成人高清一区二区| 国产福利资源一区| 99久久激情| 日韩一区二区三区在线看| 日本在线视频一区二区| 国产欧美日韩视频在线| 91麻豆国产自产在线观看亚洲| 日韩一级不卡| 日本一区二区三区视频在线看| 日韩精品久久理论片| 欧美激情福利| 亚洲黄页一区| 欧美一区精品| 免费国产自久久久久三四区久久 | 日本视频一区二区| 中文在线免费视频| 亚洲丝袜啪啪| 欧美三级网址| 久久99蜜桃| 亚洲激情精品| 欧美精品91| 亚洲尤物在线| 国内亚洲精品| 欧美丰满日韩| 亚洲毛片在线免费| 日本欧美不卡| 国产欧美一区二区三区精品观看 | 欧美在线首页| 精品91久久久久| 精品久久97| 欧美日韩一区二区三区不卡视频 | 久久久久亚洲| 免费精品国产的网站免费观看| 97精品国产福利一区二区三区| 欧美成a人免费观看久久| 日韩精品三级| 一本一道久久a久久| 日韩精品免费一区二区三区| 久久的色偷偷| 欧美天堂在线| 中文字幕乱码亚洲无线精品一区| 久久久久国产精品一区二区| 国产精品videossex| 欧美天堂一区| 久久激情综合网| 欧美综合精品| 欧美综合精品| 国产日韩欧美在线播放不卡| 亚洲精品黄色| 国产免费成人| 美女尤物久久精品| 视频一区二区三区中文字幕| 91高清一区| 亚洲一区免费| 亚洲开心激情| 日本国产欧美| 欧美亚洲色图校园春色| 国产精品调教视频| 久久91视频| 日本不良网站在线观看| 久久一区二区三区电影| 最新日韩av| 免费视频久久| 日韩二区在线观看| 日韩三区四区| 日韩精品视频中文字幕| 欧美久久精品| 日本在线高清| 亚洲午夜国产成人| 久久永久免费| 亚洲精品在线观看91| 欧美日韩国产欧| 久久精品凹凸全集| 五月激情久久| 免费日韩一区二区| 国产精品成人3p一区二区三区| 麻豆精品少妇| 久久精品播放| 国产日韩精品视频一区二区三区| 国产精品亚洲片在线播放| 精品国产亚洲一区二区三区大结局| 日韩精品1区| 日韩不卡免费视频| 日韩伦理一区| 欧美一区成人| 香蕉久久夜色精品国产| 国产精品久久免费视频| 国产亚洲福利| 国产 日韩 欧美一区| 日韩高清电影一区| 午夜欧美精品久久久久久久| 精品国产一区二区三区av片| 日韩在线一二三区| 91精品综合| 国产伦精品一区二区三区视频| 久久久久99| 国产精品不卡| 欧美国产精品| 亚洲a成人v| 丝袜国产日韩另类美女| av亚洲一区二区三区| 国产精品传媒麻豆hd| 日本不卡视频在线| 亚洲免费资源| 日本不卡视频在线观看| 一区二区精彩视频| 鲁大师成人一区二区三区| 亚洲不卡av不卡一区二区| 精品视频黄色| 国产精品红桃| 国产欧美日韩一级| 久久wwww| 精品视频亚洲| 欧美天堂视频| 在线亚洲人成| 久久人人99| 中文亚洲免费| 蜜桃久久精品一区二区| 午夜久久av| 国产精品伊人| 精品国产不卡一区二区| 高清不卡一区| 久久不见久久见中文字幕免费| 免费观看在线色综合| 99国产精品视频免费观看一公开 | 国产精品1区| 免费在线欧美黄色| 国产一区一一区高清不卡| 粉嫩av一区二区三区四区五区 | 亚洲自拍另类| 日韩精品视频网站| 国产精品欧美三级在线观看| 日韩福利在线观看| 国产精品白丝久久av网站| 久久丁香四色| 久久蜜桃av| 视频一区日韩| 三上亚洲一区二区| 群体交乱之放荡娇妻一区二区| 好看不卡的中文字幕| 日韩精品中文字幕一区二区| 精品一区二区三区中文字幕视频 | 亚洲毛片视频| av资源亚洲| 亚洲不卡视频| 日本不良网站在线观看| 在线亚洲一区| 亚洲网址在线观看| 日韩国产一区二区三区| 欧美日韩国产免费观看| 国产精品久久| 日韩视频中文| 国产精品免费大片| 日韩久久电影| 国产精品日本一区二区三区在线 | 久久不射中文字幕| 国产一区二区三区黄网站| 丝瓜av网站精品一区二区 | 亚洲一区二区三区四区五区午夜| 国产精品毛片视频| 日韩中文字幕麻豆| 午夜av不卡| 免费一区二区三区在线视频| 日韩精品一二区| 久久久9色精品国产一区二区三区| 石原莉奈在线亚洲三区| 久久中文视频| 亚洲黄色中文字幕| 久久这里只有| 国产人成精品一区二区三| 一区二区三区四区日韩| 国产精品日韩久久久| 综合日韩av| 精品视频一二| 日韩88av| 国产精品久久久免费| 日韩av一二三| 日韩成人一级| 国产毛片精品久久| 国产精品一区二区三区四区在线观看 | 欧美日韩午夜电影网| 亚洲三级视频| 日韩在线网址|