zoukankan      html  css  js  c++  java
  • RxPermissions中观察者模式解析

    RxPermissons是什么

    RxPermissions是一款基于RxJava的Android动态权限管理库。Android从6.0开始引入动态权限管理,不同于以往的APP安装时就授权完毕,对于敏感权限必须由用户手动的在APP运行过程中授权。此举对用户十分友好,但是对于程序员来说就不得不对权限进行管理。如果使用系统原生的方法进行管理,一般方式如下

    private void requestPermission() {
            if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)!= PackageManager.PERMISSION_GRANTED) {
                // 第一次请求权限时,用户如果拒绝,下一次请求shouldShowRequestPermissionRationale()返回true
                if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) {
                    // 第一次申请时提示
                } else {
                    //申请相机权限
                    ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.CAMERA}, CAMERA_REQUEST_CODE);
                }
            } else {
                tvPermissionStatus.setTextColor(Color.GREEN);
                tvPermissionStatus.setText("相机权限已申请");
            }
    }
    申请相机权限

      重写Activity或Fragment中的两个方法

    @Override
        public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            if (requestCode == CAMERA_REQUEST_CODE) {
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                    tvPermissionStatus.setTextColor(Color.GREEN);
                    tvPermissionStatus.setText("相机权限已申请");
                } else {
                    //用户勾选了不再询问
                    //提示用户手动打开权限
                    if (!ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) {
                        Toast.makeText(this, "相机权限已被禁止", Toast.LENGTH_SHORT).show();
                    }
                }
            }
        }
    View Code

      可见需要一个地方申请,然后在另外的地方再进行其他的逻辑操作。那么如果涉及到多个权限的话,onRequestPermissionsResult()方法必然很臃肿,很混乱。那么RxPermissions是怎么做的呢?

    RxPermissions如何使用

    1. 获取RxPermissions对象
    2. 通过RxPermissions对象的request()方法请求权限,链式调用subscribe(),将授权结果与rxPermission对象绑定
    3. 对RxPermission返回的状态进行判断并进行下一步操作
    final RxPermissions rxPermissions = new RxPermissions(this);
    // Must be done during an initialization phase like onCreate
    rxPermissions
        .request(Manifest.permission.CAMERA)
        .subscribe(granted -> {
            if (granted) { // Always true pre-M
               // I can control the camera now
            } else {
               // Oups permission denied
            }
        });
    View Code

      代码量并不会减少,但是整个逻辑非常简洁。请求——>绑定——>响应。

    RxPermissions解析

      RxPermissions源码

      RxPermissions一共就只有三个类

      • Permission.用来存放具体的权限名称及其是否被授权
      • RxPermissionFragment.Android中请求权限需要在Activity或者Fragment中响应onRequestPermissionsResult()回调,这个类用来做实际的权限请求级响应工作。
      • RxPermissions.调用RxPermissionFragment进行权限申请,并将结果转换后响应给调用者。

      单例方式初始化

        public RxPermissions(@NonNull final FragmentActivity activity) {
            mRxPermissionsFragment = getLazySingleton(activity.getSupportFragmentManager());
        }

      进行权限请求

      我们通过三种方式的request进行权限请求,都会返回一个Observable对象。这个被观察者通过使用ensure()方法最终调用requestImplementation(),将perissions封装在其内部。

    /**
         * Request permissions immediately, <b>must be invoked during initialization phase
         * of your application</b>.
         */
        @SuppressWarnings({"WeakerAccess", "unused"})
        public Observable<Boolean> request(final String... permissions) {
            return Observable.just(TRIGGER).compose(ensure(permissions));
        }
    
        /**
         * Request permissions immediately, <b>must be invoked during initialization phase
         * of your application</b>.
         */
        @SuppressWarnings({"WeakerAccess", "unused"})
        public Observable<Permission> requestEach(final String... permissions) {
            return Observable.just(TRIGGER).compose(ensureEach(permissions));
        }
    
        /**
         * Request permissions immediately, <b>must be invoked during initialization phase
         * of your application</b>.
         */
        public Observable<Permission> requestEachCombined(final String... permissions) {
            return Observable.just(TRIGGER).compose(ensureEachCombined(permissions));
        }

      requestImplementation通过RxPermissionsFragment进行权限请求

    @TargetApi(Build.VERSION_CODES.M)
        private Observable<Permission> requestImplementation(final String... permissions) {
            // ....
            // ....
                    mRxPermissionsFragment.get().setSubjectForPermission(permission, subject);
                }
    
                list.add(subject);
            }
    
            if (!unrequestedPermissions.isEmpty()) {
                String[] unrequestedPermissionsArray = unrequestedPermissions.toArray(new String[unrequestedPermissions.size()]);
                requestPermissionsFromFragment(unrequestedPermissionsArray);
            }
            return Observable.concat(Observable.fromIterable(list));
        }

      授权结果响应

      最终在RxPermissionsFragment中,通过onNext及onComplete通知观察者状态变化,并将授权结果返回。

    void onRequestPermissionsResult(String permissions[], int[] grantResults, boolean[] shouldShowRequestPermissionRationale) {
            for (int i = 0, size = permissions.length; i < size; i++) {
                log("onRequestPermissionsResult  " + permissions[i]);
                // Find the corresponding subject
                PublishSubject<Permission> subject = mSubjects.get(permissions[i]);
                if (subject == null) {
                    // No subject found
                    Log.e(RxPermissions.TAG, "RxPermissions.onRequestPermissionsResult invoked but didn't find the corresponding permission request.");
                    return;
                }
                mSubjects.remove(permissions[i]);
                boolean granted = grantResults[i] == PackageManager.PERMISSION_GRANTED;
                subject.onNext(new Permission(permissions[i], granted, shouldShowRequestPermissionRationale[i]));
                subject.onComplete();
            }
        }

     总结

      RxPermissions是通过RxJava,将一个Permission封装进一个Observable。接着使用RxJava的map、buffer等操作符对一个或多个Permission进行转换,在此过程中进行权限请求。在请求权限结束后更新Obvervable的状态,观察者再根据状态去读取是否授权信息。

    关于RxJava

      RxJava是一个使用观察者模式实现的响应式库,在处理异步时,虽然程序逻辑可能越来越复杂,但是它仍可以保持简洁。

      参考链接:

      RxJava详解

  • 相关阅读:
    Ubuntu分区挂载
    YOLOv3:Demo needs OpenCV for webcam images
    tf.strided_slice函数
    numpy:np.random.seed()
    python:split()函数
    python:set() 函数
    python:zip() 函数
    python:enumerate 函数
    电脑无法上网,DNS出现fec0:0:0:ffff::1%1问题
    python:map 函数
  • 原文地址:https://www.cnblogs.com/hitomeng/p/9829709.html
Copyright © 2011-2022 走看看