一蔚晨、感悟
看了源碼后乍钻,有個感慨,就是以后源碼的分析還是自己先看铭腕,看不懂再去看人家寫的银择,因為自己看思路把握得更加好,看人家的也更容易看懂谨履。
二欢摄、使用
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) {
//權(quán)限同意后的操作
} else {
//權(quán)限拒絕后的操作
}
}
});
三、分析
fragment簡稱碎片笋粟,可以嵌入到Activity中怀挠,沒想到它還可以這樣用
對比:
一般的動態(tài)請求權(quán)限是
詢問-->同意授權(quán)/不同意授權(quán)-->method-->end
詢問-->回調(diào)-->同意/不同意授權(quán)-->end
RxPermissions
詢問-->同意授權(quán)/不同意授權(quán)-->method-->end
詢問-->(fragment回調(diào))-->同意/不同意授權(quán)-->end
思路(前提是已經(jīng)了解了rxjava基礎(chǔ))
可見RxPermissions會直接隱藏掉了回調(diào)的步驟,原因就是利用rxjava的觀察者模式
1.對于授權(quán)或者沒有授權(quán)的情況害捕,換句話就是已經(jīng)有結(jié)果了的情況绿淋,會直接返回帶有結(jié)果的Observable
2.對于需要詢問的情況,記錄需要詢問的權(quán)限尝盼,然后調(diào)用詢問的方法吞滞,之后將結(jié)果以同樣的方式返回Observable
3.有了帶結(jié)果的Observable,就可以直接根據(jù)結(jié)果調(diào)方法
源碼分析
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.將權(quán)限傳遞過來
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);
}
});
}
};
}
首先關(guān)注flatMap操作符后的操作,最后返回權(quán)限的集合裁赠,遍歷集合殿漠,通過封裝權(quán)限類的第二個參數(shù)得到是否同意權(quán)限,返回布爾值佩捞。
再往上看buffer绞幌,目的是將所有權(quán)限以一個集合返回
再往上看requset操作符,點擊進(jìn)去
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);
}
});
}
進(jìn)而看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)) {
// 同意權(quán)限情況
list.add(Observable.just(new Permission(permission, true, false)));
continue;
}
if (isRevoked(permission)) {
// 拒絕權(quán)限情況
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) {
//需要詢問的權(quán)限的添加
unrequestedPermissions.add(permission);
subject = PublishSubject.create();
mRxPermissionsFragment.setSubjectForPermission(permission, subject);
}
list.add(subject);
}
if (!unrequestedPermissions.isEmpty()) {
//需要詢問的權(quán)限列表
String[] unrequestedPermissionsArray = unrequestedPermissions.toArray(new String[unrequestedPermissions.size()]);
//請求權(quán)限詢問
requestPermissionsFromFragment(unrequestedPermissionsArray);
}
return Observable.concat(Observable.from(list));
}
可以先看注釋一忱,已經(jīng)有權(quán)限請求結(jié)果的就不用再次詢問了莲蜘,直接just 發(fā)送就好。對于新的權(quán)限請求帘营,則需要調(diào)用mRxPermissionsFragment中的方法進(jìn)行詢問票渠,詢問后onNext()發(fā)送出去。
方法的最后返回Observable.concat(Observable.from(list))芬迄,是所有的請求有序發(fā)出
有關(guān)詢問的方法问顷,細(xì)看mRxPermissionsFragment中的此方法
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();
}
}
完成到這里,就基本上將所有請求全部發(fā)出薯鼠,而且經(jīng)歷多次轉(zhuǎn)換拿到了權(quán)限的請求結(jié)果择诈,被觀察者已經(jīng)完成任務(wù)了,剩下的就交給觀察者啦出皇,回看文章開頭的使用方法吧
喵印~~