Android RxPermissions源码分析

作者: 蓝库知识 | 来源:发表于2019-04-26 19:20 被阅读10次
    一、感悟

    看了源码后,有个感慨,就是以后源码的分析还是自己先看,看不懂再去看人家写的,因为自己看思路把握得更加好,看人家的也更容易看懂。

    二、使用

    RxPermissions rxPermissionss = new RxPermissions(this);
    rxPermissionss.request(Manifest.permission.READ_PHONE_STATE)
                        .subscribe(new Subscriber<Boolean>(this) {
    
                            @Override
                            public void onNext(Boolean aBoolean) {
                                if (aBoolean) {
                                   //权限同意后的操作
                                } else {
                                 //权限拒绝后的操作
                                }
                            }
                        });
    

    三、分析

    fragment简称碎片,可以嵌入到Activity中,没想到它还可以这样用

    对比:

    一般的动态请求权限是
    1.询问-->回调-->同意授权-->method-->end
    2.询问-->回调-->不同意授权-->end
    3.询问-->已授权/未授权-->method-->end
    RxPermissions
    询问-->同意授权-->method-->end
    询问-->不同意授权-->end

    思路(前提是已经了解了rxjava基础)

    可见RxPermissions会直接省略掉回调的步骤,原因就是利用rxjava的观察者模式
    1.对于授权或者没有授权的情况,换句话就是已经有结果了的情况,会直接返回带有结果的Observable
    2.对于需要询问的情况,记录需要询问的权限,然后重写询问的方法,之后将结果以同样的方式返回Observable
    3.有了带结果的Observable,就可以直接根据结果调方法

    源码分析

    1.为Activity添加fragment

    private RxPermissionsFragment getRxPermissionsFragment(Activity activity) {
            RxPermissionsFragment rxPermissionsFragment = findRxPermissionsFragment(activity);
            boolean isNewInstance = rxPermissionsFragment == null;
            if (isNewInstance) {
                rxPermissionsFragment = new RxPermissionsFragment();
                FragmentManager fragmentManager = activity.getFragmentManager();
                fragmentManager
                        .beginTransaction()
                        .add(rxPermissionsFragment, TAG)
                        .commitAllowingStateLoss();
                fragmentManager.executePendingTransactions();
            }
            return rxPermissionsFragment;
        }
    
        private RxPermissionsFragment findRxPermissionsFragment(Activity activity) {
            return (RxPermissionsFragment) activity.getFragmentManager().findFragmentByTag(TAG);
        }
    

    2.将权限传递过来

     public Observable<Boolean> request(final String... permissions) {
            return Observable.just(null).compose(ensure(permissions));
        }
    

    3.看ensure方法

    public Observable.Transformer<Object, Boolean> ensure(final String... permissions) {
            return new Observable.Transformer<Object, Boolean>() {
                @Override
                public Observable<Boolean> call(Observable<Object> o) {
                    return request(o, permissions)
                            // Transform Observable<Permission> to Observable<Boolean>
                            .buffer(permissions.length)
                            .flatMap(new Func1<List<Permission>, Observable<Boolean>>() {
                                @Override
                                public Observable<Boolean> call(List<Permission> permissions) {
                                    if (permissions.isEmpty()) {
                                        // Occurs during orientation change, when the subject receives onComplete.
                                        // In that case we don't want to propagate that empty list to the
                                        // subscriber, only the onComplete.
                                        return Observable.empty();
                                    }
                                    // Return true if all permissions are granted.
                                    for (Permission p : permissions) {
                                        if (!p.granted) {
                                            return Observable.just(false);
                                        }
                                    }
                                    return Observable.just(true);
                                }
                            });
                }
            };
        }
    

    首先关注flatMap操作符后的操作,就是返回包含权限请求结果的Observable。
    再往上看requset操作符

    private Observable<Permission> request(final Observable<?> trigger, final String... permissions) {
            if (permissions == null || permissions.length == 0) {
                throw new IllegalArgumentException("RxPermissions.request/requestEach requires at least one input permission");
            }
            return oneOf(trigger, pending(permissions))
                    .flatMap(new Func1<Object, Observable<Permission>>() {
                        @Override
                        public Observable<Permission> call(Object o) {
                            return requestImplementation(permissions);
                        }
                    });
        }
    

    进而看requestImplementation方法

    private Observable<Permission> requestImplementation(final String... permissions) {
            List<Observable<Permission>> list = new ArrayList<>(permissions.length);
            List<String> unrequestedPermissions = new ArrayList<>();
    
            // In case of multiple permissions, we create an Observable for each of them.
            // At the end, the observables are combined to have a unique response.
            for (String permission : permissions) {
                mRxPermissionsFragment.log("Requesting permission " + permission);
                if (isGranted(permission)) {
                    // 同意权限情况
                    list.add(Observable.just(new Permission(permission, true, false)));
                    continue;
                }
    
                if (isRevoked(permission)) {
                    // 拒绝权限情况
                    list.add(Observable.just(new Permission(permission, false, false)));
                    continue;
                }
    
                PublishSubject<Permission> subject = mRxPermissionsFragment.getSubjectByPermission(permission);
                // Create a new subject if not exists
                if (subject == null) {
                    //需要询问的权限的添加
                    unrequestedPermissions.add(permission);
                    subject = PublishSubject.create();
                    mRxPermissionsFragment.setSubjectForPermission(permission, subject);
                }
    
                list.add(subject);
            }
    
            if (!unrequestedPermissions.isEmpty()) {
             //需要询问的权限列表
                String[] unrequestedPermissionsArray = unrequestedPermissions.toArray(new String[unrequestedPermissions.size()]);
            //请求权限询问
        requestPermissionsFromFragment(unrequestedPermissionsArray);
            }
            return Observable.concat(Observable.from(list));
        }
    
    

    可以先看注释,然后注意
    mRxPermissionsFragment.setSubjectForPermission(permission, subject);
    此方法中注意mRxPermissionsFragment这个类,这个类主要是处理请求权限询问结果的,处理完通过subject发出来
    细看此方法

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

    先写这么多,后续再补充

    喵印~~

    相关文章

      网友评论

        本文标题:Android RxPermissions源码分析

        本文链接:https://www.haomeiwen.com/subject/viyggqtx.html