玩转ActivityResultLauncher领略设计之美

本文探讨了如何在Android中利用ActivityResultLauncher进行权限请求的封装,通过设计思维简化代码,包括IPermissionHelper和IPermissionChecker的构建,以及在不同场景下的应用。同时,文章介绍了开源的权限请求库,提供了一种更简洁的权限管理方式。
摘要由CSDN通过智能技术生成

玩转ActivityResultLauncher领略设计之美

ActivityResultLauncher 作为新一代的 RsultApi,其目的用于简化页面中跳转获取返回值以及请求权限。

ActivityResultLauncher 在某些场景下确会出现模板过多,不好用的场景,譬如以下这一场景:ActivityResultLauncher 在一个页面中不同的业务场景请求不同的权限的场景。

面对这样的情况,我们是盲目使用第三库去完成请求权限功能?还是通过一些设计思维对封装 ActivityResultLauncher 使用?这一场景下的 ActivityResultLauncher 何去何从?面对这样的场景。我坚决的奉行自己动手丰衣足食,真的是丰衣给足食开门。

ActivityResultLauncher 优缺点

ActivityResultLauncher 作为新一代的 RsultApi

优点在于通过单一原则,通过单独对应的回调专门处理对应业务逻辑;譬如下面这一段伪代码对比


//旧时代API处理页面跳转逻辑
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
   
        super.onActivityResult(requestCode, resultCode, data)
        when(requestCode){
   
            getPerssionPhoneCode->{
   
           		//do your logic   
            }
            getImageCode->{
   
               //do your logic 
            }
// more example           
        }
    }

//新一代api处理方式 以登录为例子
class LoginResultContractDemo : ActivityResultContract<Boolean, Boolean>() {
   

    //跳转登录页面
    override fun createIntent(context: Context, input: Boolean?): Intent {
   
        return Intent(context, ActivityResultLauncherLoginDemoActivity::class.java)
    }

    //处理登录页面回调结果
    override fun parseResult(resultCode: Int, intent: Intent?): Boolean {
   

        if (resultCode == Activity.RESULT_OK) {
   
            
            return intent?.getBooleanExtra(
                ActivityResultLauncherLoginDemoActivity.LOGIN_RESULT_TAG,
                false) ?: false
        }
        return false
    }
}

class ActivityResultLauncherDemoActivity : AppCompatActivity() {
   

    private val loginLauncher = 
    		registerForActivityResult(LoginResultContractDemo()) {
    result ->
//结果回调
        Toast.makeText(this, 
                       if (result) "登录成功" else "登录失败", Toast.LENGTH_SHORT).show()

    }
      
    override fun onCreate(savedInstanceState: Bundle?) {
   
       //启用launcher去进行页面跳转
        toLogin.setOnClickListener {
   loginLauncher.launch(false)}
    }
}

优点在于:

  • ActivityResultContract 作为单一职责:负责处理页面跳转传参以及页面结果的回调处理
  • ActivityResultCallback 仅负责将 ActivityResultContract 中的目标页面的期望结果进行输出回调即可
  • ActivityResultLauncher 负责将 ActivityResultContract 以及 ActivityResultCallback 关联起来
  • 使用这三者抛离旧时代API的中回调各种复杂判断通过使用这样的解耦关系使得每一个页面更加简便清爽,并可以进行抽离封装复用。

缺点在于面对通用场景时,单一原则会导致冗余的模板代码。

下面就用常见的请求权限场景展示这个缺点

class ActivityResultLauncherDemoActivity : AppCompatActivity() {
   

    private val userLocationPermission = registerForActivityResult(
            ActivityResultContracts.RequestMultiplePermissions()) {
    map ->

           //判断是否有存在用户拒绝某些权限                                                   
            val failMultiplePermission = ArrayList<String>()

            map.forEach {
    entry ->

                if (!entry.value) {
   
                    failMultiplePermission.add(entry.key)
                }
            }

            if (failMultiplePermission.isNullOrEmpty()) {
   
			//获取用户位置信息
                toUserLocationLogic()
                return@registerForActivityResult
            }
			//用户位置获取失败逻辑
            loseUserLocationLogic()
        }
    
        private val imagePermission = registerForActivityResult(
            ActivityResultContracts.RequestMultiplePermissions()) {
    map ->

           //判断是否有存在用户拒绝某些权限                                                   
            val failMultiplePermission = ArrayList<String>()

            map.forEach {
    entry ->

                if (!entry.value) {
   
                    failMultiplePermission.add(entry.key)
                }
            }

            if (failMultiplePermission.isNullOrEmpty()) {
   
			//获取用户位置信息
                getImage()
                return@registerForActivityResult
            }
			//用户位置获取失败逻辑
            loseImage()
        }
    
    override fun onCreate(savedInstanceState: Bundle?) {
   
        super.onCreate(savedInstanceState)

         binding = ActivityResultLauncherDemoBinding.inflate(layoutInflater)
        
         bingding.userLocation.setOnClickListenr{
   
             //请求位置权限
             userLocationPermission.launcher(arrayof())
         }
        
         bingding.image.setOnClickListenr{
   
             //请求位置权限
             imagePermission.launcher(arrayof())
         }
    }
}

面对上面弊端能不能通过一个抽象方式的思维去简化封装呢?

从抽象到实现的一小步

期望中的抽象

我希望这个权限请求库的流程时序是这样的:

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值