自從6.0加入動態(tài)權限之后拭抬,很多地方都要用到苍狰,開始的時候使用的原生代碼寫權限請求闪水,代碼格式如:
if(應用是否已經(jīng)請求了該權限組){
權限請求后的代碼
}else{
請求權限
}
然后不知道在fragment或是activity里面重寫
override onRequestPermissionsResult{
if(請求成功){
權限請求后的代碼
}else{
失敗處理
}
}
不知道你們對這種代碼是什么感覺午衰,反正我是很不喜歡這樣的代碼淘捡,和不喜歡startActivityForResult還有handle一樣嘿辟,由于今年來rxjava大火舆瘪,我首先想到的是能不能用rxjava來封裝片效,果然,git上一搜英古,就搜到RxPermissions和RxStartActivityForResult這兩個項目淀衣,這種寫法優(yōu)化了原生代碼那種離散的寫法,增加了代碼的可讀性召调,代碼變?yōu)?/p>
new RxPermissions(activity)
.request(權限數(shù)組)
.subscribe(){
if(權限請求成功){
{
}
瞬間簡潔了不少膨桥,不過考慮到我的很多項目都接入了協(xié)程,也覺得協(xié)程的順序?qū)懛勺x性簡潔性和可維護性都更強唠叛,希望能夠找到請求權限的協(xié)程解決方案只嚣,在網(wǎng)上找了很久也沒找到相關方案,找startActivityForResult的時候卻找到了startActivityForResult的協(xié)程解決方案InlineActivityResult艺沼,于是參考了他的設計思想册舞,最終實現(xiàn)了動態(tài)權限請求的協(xié)程寫法,用kotlin協(xié)程實現(xiàn)動態(tài)權限請求
用法很簡單:
CoroutineScope(Dispatchers.Main).launch {
try {
requestPermissionForResult(*permissions)//權限請求
權限請求成功后執(zhí)行的代碼
}catch (e: InlineRequestPermissionException) {
權限請求失敗后執(zhí)行的代碼
}
}
因為語法要求障般,所以在執(zhí)行權限請求前要先開啟一個協(xié)程CoroutineScope(Dispatchers.Main).launch调鲸,因為是在Activity或是fragment中請求,所以最好在協(xié)程中指定主線程Dispatchers.Main
trycatch是因為要處理權限取消或是權限請求失敗后的流程挽荡,也可以在設計的時候集中處理權限請求失敗后的流程藐石,這樣就可以不用寫trycatch,這就涉及到協(xié)程的異常處理了
CoroutineScope(Dispatchers.Main).launch {
requestPermissionForResult(*permissions)//權限請求
權限請求成功后執(zhí)行的代碼
}
另外trycatch也可以和其他協(xié)程共用,這樣trycatch就不是專門為某個協(xié)程而生了
CoroutineScope(Dispatchers.Main).launch {
try {
requestPermissionForResult(*permissions)//權限請求協(xié)程寫法
權限請求成功后執(zhí)行的代碼
val result=startForResult(activity)//startActivityForResult協(xié)程寫法
startActivityForResult返回代碼
}catch (e: InlineRequestPermissionException) {
權限請求失敗后執(zhí)行的代碼
}catch(e: InlineRequestPermissionException){
startActivityForResult返回異常處理
}
}
實現(xiàn)原理也不復雜徐伐,思路是請求權限的時候在Activity中創(chuàng)建一個無界面fragment,提交fragment事務的時候不要提交到回退棧(commitNowAllowingStateLoss)贯钩,在該fragment中重寫onRequestPermissionsResult方法接收請求結(jié)果,完畢之后移除fragment事務,然后用協(xié)程封裝方法封裝办素;這樣做的好處是整個權限請求過程和原請求的Activity/Fragment解耦角雷,無需關心請求過程,也無需重寫onRequestPermissionsResult去接收請求
無界面fragment提交事務方式:
activity.supportFragmentManager
.beginTransction()
.add(fragment,Tag)
.commitNowAllowingStateLoss()
無界面fragment移除
fragmentManager.beginTransaction().remove(this).commitAllowingStateLoss()
最后用協(xié)程封裝
當然原理還是比較簡單性穿,實現(xiàn)過程也不算復雜勺三,這是項目地址:用kotlin協(xié)程實現(xiàn)動態(tài)權限請求