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

先寫這麼多,後續再補充

喵印~~

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