RxPermission 源码解读
2019-09-25 本文已影响0人
BrokenDust
使用的技术
- RxJava
- Fragment
原理描述
1569382934(1).jpg通过向申请权限的Fragment 或 Activity 中添加一个没有布局的Fragment来申请权限,使用Fragment的相关权限申请方法,来申请权限。然后通过RxJava 的 PublishSubject 特性 将授权结果发送给申请的地方
代码流程
-
发起申请
// 申请者可以为 activity public RxPermissions(@NonNull final FragmentActivity activity) { mRxPermissionsFragment = getLazySingleton(activity.getSupportFragmentManager()); } // 申请者可以为 fragment public RxPermissions(@NonNull final Fragment fragment) { mRxPermissionsFragment = getLazySingleton(fragment.getChildFragmentManager()); }
-
向当前申请者布局内添加一个没有布局的fragment
private RxPermissionsFragment getRxPermissionsFragment(@NonNull final FragmentManager fragmentManager) {
RxPermissionsFragment rxPermissionsFragment = findRxPermissionsFragment(fragmentManager);
boolean isNewInstance = rxPermissionsFragment == null;
if (isNewInstance) {
rxPermissionsFragment = new RxPermissionsFragment();
fragmentManager
.beginTransaction()
.add(rxPermissionsFragment, TAG)
.commitNow();
}
return rxPermissionsFragment;
}
-
遍历授权请求 添加到观察者集合中
// 返回Observable供申请者订阅 @TargetApi(Build.VERSION_CODES.M) private Observable<Permission> requestImplementation(final String... permissions) { List<Observable<Permission>> list = new ArrayList<>(permissions.length); List<String> unrequestedPermissions = new ArrayList<>(); // 使用者可能一次申请了多个权限,将每个权限转换成一个权限被观察者,然后再将这些权限被观察者连接起来 for (String permission : permissions) { mRxPermissionsFragment.get().log("Requesting permission " + permission); //已经被授权了或者是6.0以下 则直接返回携带true的权限被观察者 if (isGranted(permission)) { list.add(Observable.just(new Permission(permission, true, false))); continue; } // 被代理则直接返回false if (isRevoked(permission)) { list.add(Observable.just(new Permission(permission, false, false))); continue; } PublishSubject<Permission> subject = mRxPermissionsFragment.get().getSubjectByPermission(permission); // Create a new subject if not exists // 正常情况下这个地方的subject都是为空 if (subject == null) { unrequestedPermissions.add(permission); subject = PublishSubject.create(); mRxPermissionsFragment.get().setSubjectForPermission(permission, subject); } list.add(subject); } if (!unrequestedPermissions.isEmpty()) { String[] unrequestedPermissionsArray = unrequestedPermissions.toArray(new String[unrequestedPermissions.size()]); //触发fragment 发起权限申请的地方 requestPermissionsFromFragment(unrequestedPermissionsArray); } // concat 为串行操作符 return Observable.concat(Observable.fromIterable(list)); }
-
无布局fragment 发起权限申请
/** * 开始请求权限 * * @param permissions */ @TargetApi(Build.VERSION_CODES.M) void requestPermissions(@NonNull String[] permissions) { requestPermissions(permissions, PERMISSIONS_REQUEST_CODE); }
-
无布局fragment 处理权限 并通过PublishSubject 发送消息出去
/**
* 权限的回调
*
* 第一次请求权限时ActivityCompat.shouldShowRequestPermissionRationale=false;
* 第一次请求权限被禁止,但未选择【不再提醒】ActivityCompat.shouldShowRequestPermissionRationale=true;
* 允许某权限后ActivityCompat.shouldShowRequestPermissionRationale=false;
* 禁止权限,并选中【禁止后不再询问】ActivityCompat.shouldShowRequestPermissionRationale=false;
*
* @param requestCode
* @param permissions
* @param grantResults
*/
@TargetApi(Build.VERSION_CODES.M)
public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode != PERMISSIONS_REQUEST_CODE) return;
boolean[] shouldShowRequestPermissionRationale = new boolean[permissions.length];
for (int i = 0; i < permissions.length; i++) {
shouldShowRequestPermissionRationale[i] = shouldShowRequestPermissionRationale(permissions[i]);
}
onRequestPermissionsResult(permissions, grantResults, shouldShowRequestPermissionRationale);
}
/**
* @param permissions 所申请的权限
* @param grantResults 拒绝与否的数组
* @param shouldShowRequestPermissionRationale 是否需要显示申请理由的数组
*/
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();
}
}
最后感想
整体库的代码比较简单,但是为我们提供了一些解决问题的思路
① 对于需要生命周期感知的问题,我们可以委托一个fragment来进行管理
② 使用PublishSubject 能够轻松实现一些基于观察者模式的需求