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();
                }
            }
        }
    }

  可见需要一个地方申请,然后在另外的地方再进行其他的逻辑操作。那么如果涉及到多个权限的话,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
        }
    });

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

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详解

原文地址:https://www.cnblogs.com/hitomeng/p/9829709.html

时间: 2024-10-18 10:02:20

RxPermissions中观察者模式解析的相关文章

Keyboard项目中观察者模式解析

该项目旨在解决输入框多层嵌套的情况下软盘和输入框位置不适配的问题. 项目的github源码链接为:https://github.com/crazycodeboy/KeyboardObserver/blob/master/KeyboardObserver/KeyboardObserver.m 一.观察者模式实现原理 观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象.当这个主题对象在状态发生变化时,会通知所有观察者对象,使得他们能够更新自己.在此项目中其实现原理主要体现在

AFNetworking 中观察者模式解析

0. Objective-C 中的观察者模式(KVO) Objective-C 语言实现了观察者模式(Key Value Observing, KVO),并提供了简单的使用接口. 供给使用者方便的注册观察者,注册观察方法,移除观察者. a. 注册观察者 /* 方法的接收者 objectA 是被观察者 objectB 观察的对象 方法的第一个参数 objectB 是注册到 objectA 上的观察者 方法的第二个参数 @"property" 是被观察者 objectB 监听的属性,当该属

iOS 中json解析数据出现中文乱码的问题

一般服务器的编码格式都是UTF8,这样通过json解析下来的的数据,一般中文是不会出现乱码,但是如果服务器的编码格式不是UTF8,通过json解析的数据中的中文容易出现luan乱码,怎么解决这个问题呢? 一般都是通过转码来解决,但是直接转码,是不能达到效果的,例如 [jsonStringstringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding] 这样直接转码是达不到效果的. 解析数据的时候,可以先把数据存放在NSdata对象中,

C# 将XML格式字符串,写入数据集的表中 XML解析

将XML格式字符串,写入数据集的表1中 命名空间:using System.Xml; string strRead;//strRead为以下xml值 XmlDocument xd = new XmlDocument(); xd.LoadXml(strRead); XmlNodeList nodeList = xd.SelectSingleNode("root").ChildNodes;//获取bookstore节点的所有子节点 foreach (XmlNode xn in nodeLi

WCF中配置文件解析

WCF中配置文件解析 2014-06-14 参考 WCF中配置文件解析 返回 在WCF Service Configuration Editor的使用中,我们通过配置工具自动生成了WCF服务端的config文件.现在我们来看下这个配置文件各个标签的意义: 1 <?xml version="1.0" encoding="utf-8" ?> 2 <configuration> 3 <!-- 这个程序集我们在项目中有引用的 --> 4

java中观察者模式Observable和Observer

25.java中观察者模式Observable和Observer 如果想要实现观察者模式,则必须依靠java.util包中提供的Observable类和Observer接口 观察者设计模式 现在很多的购房者都在关注着房子的价格变化,每当房子价格变化的时候,所有的购房者都可以观察得到. 实际上以上的购房者就是观察者,他们所关注的房价就是被观察者 其中要求,被观察者需要继承Observable类,观察则需要实现Observer接口 具体实现如下 房价的实现 1 class House extends

json格式数据2中方式解析实例

json格式数据2中方式解析实例 json是移动平台上非常常用的数据传输格式,本示例提供了两种Json格式文件生成与解析的方式.第一种通过JsonReader和JsonWriter两个对象进行json文件的读写操作,需要sdk在11以上.第二种通过JSONArray.JSONObject.JSONTokener等对象进行json读写操作,需要sdk在9以上.这种方式也可通过引入jar包的方式在其他版本的sdk中实现.启动客户端后,先点击写入json按钮(第1或3个按钮)生成Json文件(位置为s

Android中XML解析-Dom解析

Android中需要解析服务器端传过来的数据,由于XML是与平台无关的特性,被广泛运用于数据通信中,有的时候需要解析xml数据,格式有三种方式,分别是DOM.SAX以及PULL三种方式,本文就简单以Dom解析为例,解析XML, DOM方式解析xml是先把xml文档都读到内存中,然后再用DOM API来访问树形结构,并获取数据的,但是这样一来,如果xml文件很大,手机CPU处理能力比PC差,因此在处理效率方面就相对差了,使用Dom解析就不是太合适了. 基础维护 首先下assets目录下新建一个Bo

Android中观察者模式的升入理解

以前对Java中的观察者模式只知道一点皮毛,在接触Android的过程中,逐渐认识到观察者模式是如此的重要,android中许多地方都用到了观察者模式例如ContentResolver操作,来总结一下android中观察者模式的使用技巧 我所理解的观察者模式是这样子的:: 以一个例子来说明: 在service中有一个int类型的数据i,我在service中启动一个定时器去不断更新这个值,当我在activity中启动这个服务一次之后,每当i变化的时候我的activity要自动的同步更新这个值来显示