内容简介:本文作者链接:
本文作者
作者: 反魂蝶五分
链接:
https://blog.csdn.net/u014290233/article/details/104383929
本文由作者授权发布。
1
概述在以前,我们项目框架通常使用Rxjava+Retrofit+okhttp,所以使用RxPermissions进行动态权限申请就顺理成章了。随着Google新技术的推出,kotlin、jetpack成为大势所趋,如果项目中没有使用Rxjava,那么依赖于Rxjava的RxPermissions也就无法适用了。
RxPermissions 利用了Rxjava的观察者模式,而jetpack也提供了一种可观察的数据存储器类——LiveData,所以可以利用LiveData完成类似RxPermissions的动态权限申请框架,而且LiveData能够感知组件的生命周期,当 Activity 和 Fragment 的生命周期被销毁时,系统会立即退订它们,避免内存泄漏。
如果观察者(由 Observer 类表示)的生命周期处于 STARTED 或 RESUMED 状态,则 LiveData 会认为该观察者处于活跃状态。LiveData 只会将更新通知给活跃的观察者。为观察 LiveData 对象而注册的非活跃观察者不会收到更改通知。
2
代码实现我们需要新建一个Fragment,用这个Fragment来进行权限的申请处理(新建Fragment的用途很广泛,比如Glide就是通过创建一个Fragment,然后通过这个Fragment感知生命周期),需要注意的是如果当前在Fragment里申请权限,需要用fragment.childFragmentManager,
class LivePermissions { ...... constructor(activity: AppCompatActivity) { liveFragment = getInstance(activity.supportFragmentManager) } constructor(fragment: Fragment) { liveFragment = getInstance(fragment.childFragmentManager) } @Volatile private var liveFragment: LiveFragment? = null private fun getInstance(fragmentManager: FragmentManager) = liveFragment ?: synchronized(this) { liveFragment ?: if (fragmentManager.findFragmentByTag(TAG) == null) LiveFragment().run { fragmentManager.beginTransaction().add(this, TAG).commitNow() this } else fragmentManager.findFragmentByTag(TAG) as LiveFragment } ...... }
权限申请方法,在这里调用Fragment的申请申请方法并返回MutableLiveData,MutableLiveData是LiveData的子类,使用setValue或者postValue传入数据,通过LiveData.observe(LifecycleOwner,Observer)传入观察者观察数据更新,这样在Fragment里通过MutableLiveData将权限申请的结果回调回去。
fun request(vararg permissions: String): MutableLiveData<PermissionResult> { return this.requestArray(permissions) } fun requestArray(permissions: Array<out String>): MutableLiveData<PermissionResult> { liveFragment!!.requestPermissions(permissions) return liveFragment!!.liveData } ...... }
创建LiveFragment继承Fragment。在requestPermissions方法里创建MutableLiveData并调用Android申请权限的方法,这里在onRequestPermissionsResult里处理返回结果。
返回结果这里创建了2个ArrayList,分别用来临时保持“拒绝”和“拒绝并不再询问”的权限,最终调用LiveData的setValue方法,利用LiveData观察者模式的特性,数据改变时会自动通知观察者。
internal class LiveFragment : Fragment() { lateinit var liveData :MutableLiveData<PermissionResult> private val PERMISSIONS_REQUEST_CODE = 100 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) retainInstance = true //旋转屏幕时保存Fragment状态 } @TargetApi(Build.VERSION_CODES.M) fun requestPermissions(permissions: Array<out String>) { liveData = MutableLiveData() requestPermissions(permissions, PERMISSIONS_REQUEST_CODE) } override fun onRequestPermissionsResult( requestCode: Int, permissions: Array<out String>, grantResults: IntArray ) { if (requestCode == PERMISSIONS_REQUEST_CODE) { val denyPermission = ArrayList<String>() val rationalePermission = ArrayList<String>() for ((index, value) in grantResults.withIndex()) { if (value == PackageManager.PERMISSION_DENIED) { if (shouldShowRequestPermissionRationale(permissions[index])) { rationalePermission.add(permissions[index]) } else { denyPermission.add(permissions[index]) } } } if (denyPermission.isEmpty() && rationalePermission.isEmpty()) { liveData.value = PermissionResult.Grant } else { if (rationalePermission.isNotEmpty()) { liveData.value = PermissionResult.Rationale(rationalePermission.toTypedArray()) } else if (denyPermission.isNotEmpty()) { liveData.value = PermissionResult.Deny(denyPermission.toTypedArray()) } } } } }
在最后返回权限的权限处理选项时,使用kotlin的sealed关键字,来确保在项目里使用when时能安全的判断每个权限每种可能的情况。
sealed class PermissionResult { object Grant : PermissionResult() //全部同意 class Deny(val permissions: Array<String>) : PermissionResult() //拒绝且勾选了不再询问,permissions——被拒绝的权限 class Rationale(val permissions: Array<String>) : PermissionResult() //只是拒绝,没有勾选不再询问,permissions——被拒绝的权限 }
代码已托管到github,欢迎star, 地址:
https://github.com/LGD2009/LivePermissions
项目已发布到jcenter,可直接引用。
3
使用方法1.添加依赖
implementation 'com.ftd.livepermissions:livepermissions:1.0.0'
2.添加代码
//申请权限 LivePermissions(this).request( Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.CAMERA ).observe(this, Observer { when (it) { is PermissionResult.Grant -> { //权限允许 Toast.makeText(this, "Grant", Toast.LENGTH_SHORT).show() } is PermissionResult.Rationale -> { //权限拒绝 it.permissions.forEach {s-> println("Rationale:${s}")//被拒绝的权限 } Toast.makeText(this, "Rationale", Toast.LENGTH_SHORT) .show() } is PermissionResult.Deny -> { //权限拒绝,且勾选了不再询问 it.permissions.forEach {s-> println("deny:${s}")//被拒绝的权限 } Toast.makeText(this, "deny", Toast.LENGTH_SHORT).show() } } })
相关资料
LiveData 概览
https://developer.android.google.cn/topic/libraries/architecture/livedata
What are sealed classes in Kotlin?
https://stackoverflow.com/questions/50772328/what-are-sealed-classes-in-kotlin?r=SearchResults
推荐阅读 :
扫一扫 关注我的公众号
如果你想要跟大家分享你的文章,欢迎投稿~
┏(^0^)┛明天见!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- LWN:利用debounce buffer来阻止恶意设备利用DMA窃取信息
- 新医药 Leon Nanodrugs完成1850万欧元A轮融资,利用粒子合成方法提高药物利用率
- JNDI 注入利用工具
- Outlook滥用利用链
- tcache机制利用总结
- LFItoRCE利用总结
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
像计算机科学家一样思考Python (第2版)
[美] 艾伦 B. 唐尼 / 赵普明 / 人民邮电出版社 / 2016-7 / 49.00
本书以培养读者以计算机科学家一样的思维方式来理解Python语言编程。贯穿全书的主体是如何思考、设计、开发的方法,而具体的编程语言,只是提供了一个具体场景方便介绍的媒介。 全书共21章,详细介绍Python语言编程的方方面面。本书从基本的编程概念开始讲起,包括语言的语法和语义,而且每个编程概念都有清晰的定义,引领读者循序渐进地学习变量、表达式、语句、函数和数据结构。书中还探讨了如何处理文件和......一起来看看 《像计算机科学家一样思考Python (第2版)》 这本书的介绍吧!