Android RxPermissions源码分析

一、感悟

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

二、使用

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

先写这么多,后续再补充

喵印~~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章