[toc]
RxPermissions 源碼解析
簡(jiǎn)介
RxPermissions 是基于 RxJava 開(kāi)發(fā)的用于幫助 在Android 6.0 中處理運(yùn)行時(shí)權(quán)限檢測(cè)的框架册舞。在 Android 6.0 中增加了對(duì)危險(xiǎn)權(quán)限的動(dòng)態(tài)申請(qǐng)安疗,而不是像 Android 6.0 之前的默認(rèn)全部獲取的方式。
原始動(dòng)態(tài)權(quán)限的獲取
如果按照以往的獲取權(quán)限方式的話晌纫,那么我們獲取權(quán)限一般需要有 3 個(gè)步驟昼榛,第一步是先判斷當(dāng)前是否已經(jīng)獲取到該權(quán)限了境肾;第 2 步申請(qǐng)對(duì)應(yīng)的權(quán)限;第 3 步在 Activity 或者 Fragment 中處理獲取權(quán)限的結(jié)果胆屿。具體的實(shí)現(xiàn)步驟如下:
- step 1:判斷權(quán)限是否已經(jīng)獲取奥喻。
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.CAMERA)) {
//用于開(kāi)發(fā)者提示用戶權(quán)限的用途
} else {
//申請(qǐng)權(quán)限
}
- step 2:申請(qǐng)權(quán)限
ActivityCompat.requestPermissions(MainActivity.this,
new String[]{Manifest.permission.CAMERA},
REQUEST_CAMERA);
- step 3:結(jié)果處理
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
// 判斷請(qǐng)求碼,確定當(dāng)前申請(qǐng)的權(quán)限
if (requestCode == REQUEST_CAMERA) {
//判斷權(quán)限是否申請(qǐng)通過(guò)
if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//授權(quán)成功
} else {
//授權(quán)失敗
}
} else {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
RxPermissions 的簡(jiǎn)單使用
其實(shí) RxPermissions 的使用方式有兩種
- 方式 1:
RxPermissions rxPermissions = new RxPermissions(MainActivity.this);
rxPermissions
.request(Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE)//這里填寫所需要的權(quán)限
.subscribe(new Consumer<Boolean>() {
@Override
public void accept(Boolean aBoolean) throws Exception {
if (aBoolean) {
// 通過(guò)
}else{
// 拒絕
}
}
});
- 方式 2:結(jié)合 RxBinding 來(lái)使用
RxPermissions rxPermissions = new RxPermissions(MainActivity.this);
// Must be done during an initialization phase like onCreate
RxView.clicks(findViewById(R.id.enableCamera))
.compose(rxPermissions.ensure(Manifest.permission.CAMERA))
.subscribe(granted -> {
// R.id.enableCamera has been clicked
});
源碼分析
整體介紹
接著我們來(lái)對(duì)這個(gè) RxPermissions 進(jìn)行一個(gè)源碼的解析非迹,但是打開(kāi)源碼的時(shí)候环鲤,我們可以發(fā)現(xiàn),這個(gè)庫(kù)里面憎兽,其實(shí)就只有 3 個(gè)類:RxPermissions冷离、RxPermissionsFragment、Permission
- RxPermissions
- 最主要的實(shí)現(xiàn)類纯命,利用 rxjava酒朵,為我們提供了方便權(quán)限申請(qǐng)的類
- RxPermissionsFragment
- 是一個(gè) fragment,主要的動(dòng)態(tài)權(quán)限獲取類
- Permission
- 定義的權(quán)限的 model 類
源碼分析
RxPermissions 實(shí)例創(chuàng)建
對(duì)于源碼的分析扎附,我們應(yīng)該先從簡(jiǎn)單的使用入手。下面我們可以先看看實(shí)例化 RxPermissionsFragment 的時(shí)候是做了什么结耀?
RxPermissionsFragment mRxPermissionsFragment;
public RxPermissions(@NonNull Activity activity) {
mRxPermissionsFragment = getRxPermissionsFragment(activity);
}
我們可以看到留夜,上面的代碼中,實(shí)例化 RxPermissionsFragment 的時(shí)候图甜,里面先創(chuàng)建了一個(gè) RxPermissionsFragment 的實(shí)例碍粥。我們?cè)俳又?getRxPermissionsFragment 這個(gè)方法的實(shí)現(xiàn)。
private RxPermissionsFragment getRxPermissionsFragment(Activity activity) {
// 查找 RxPermissionsFragment 是否已經(jīng)被添加了
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;
}
在 getRxPermissionsFragment() 這個(gè)方法中黑毅,首先是先查找當(dāng)前是否已經(jīng)添加了這個(gè) rxPermissionsFragment 的實(shí)例嚼摩,如果已經(jīng)添加,那么直接返回已經(jīng)添加的實(shí)例,如果沒(méi)有添加過(guò)的話枕面,那么就重新再創(chuàng)建一個(gè) RxPermissionsFragment 實(shí)例并提交愿卒;
private RxPermissionsFragment findRxPermissionsFragment(Activity activity) {
return (RxPermissionsFragment) activity.getFragmentManager().findFragmentByTag(TAG);
}
到此,rxPermissionsFragment 的實(shí)例化已經(jīng)完成潮秘,接著我們需要看看 request 這個(gè)方法中實(shí)現(xiàn)了什么琼开。
request 方法
public Observable<Boolean> request(final String... permissions) {
return Observable.just(TRIGGER).compose(ensure(permissions));
}
static final Object TRIGGER = new Object();
從上面的代碼中,我們可以看到枕荞,request 方法中需要傳入的參數(shù)是一個(gè) 權(quán)限的數(shù)組柜候,返回值是 Observable<Boolean> 對(duì)象。Observable.just(TRIGGER) 是快捷創(chuàng)建一個(gè) Observable 的方式躏精,由于 TRIGGER 是一個(gè)空的 Object 對(duì)象渣刷,所以 TRIGGER 就是一個(gè)占位符而已,Observable.just(TRIGGER) 創(chuàng)建的是一個(gè) Observable<Object>,之后通過(guò) compose 將 Observable<Object> 轉(zhuǎn)化為 Observable<Boolean> 并返回矗烛。在 compose 中需要的參數(shù)是一個(gè) ObservableTransformer辅柴,那么我們接著看 ensure() 這個(gè)方法。
ensure(permissions);
public <T> ObservableTransformer<T, Boolean> ensure(final String... permissions) {
// 創(chuàng)建一個(gè)Transformer對(duì)象返回
return new ObservableTransformer<T, Boolean>() {
@Override
public ObservableSource<Boolean> apply(Observable<T> o) {
//request(o, permissions) 方法返回 Observable<Permission> 對(duì)象
return request(o, permissions)
// 將 Observable<Permission> 轉(zhuǎn)換為 Observable<Boolean>高诺,在這里會(huì)等待所有的權(quán)限都返回了一次性發(fā)射數(shù)據(jù)碌识。
.buffer(permissions.length)
.flatMap(new Function<List<Permission>, ObservableSource<Boolean>>() {
@Override
public ObservableSource<Boolean> apply(List<Permission> permissions) throws Exception {
// 如果permissions為空那么直接返回Observable.empty();
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);
}
});
}
};
}
在 ensure 的這個(gè)方法中,最終會(huì)返回的是 ObservableTransformer<T, Boolean> 對(duì)象虱而。接著我們看看 ObservableTransformer 的匿名實(shí)現(xiàn)類里面的 apply 方法筏餐,這里實(shí)現(xiàn)的就是將 Observable<Permission> 轉(zhuǎn)換為 Observable<Boolean> 的操作。我們對(duì) apply 這個(gè)方法里面的代碼進(jìn)行簡(jiǎn)化一下牡拇。
return request(o,permissions)
.buffer(permissions.length)
.flatMap(new Function<List<Permission>, ObservableSource<Boolean>>{});
- request() 方法返回 Observable<Permission> 對(duì)象
- buffer(len) 操作符將一個(gè) Observable<Permission> 變換為 Observable<List<Permission>>魁瞪,原來(lái)的 Observable 正常發(fā)射數(shù)據(jù),變換產(chǎn)生的 Observable 發(fā)射這些數(shù)據(jù)的緩存集合惠呼。buffer 將數(shù)據(jù)緩存到一個(gè)集合當(dāng)中导俘,然后在適當(dāng)(比如:所有請(qǐng)求的權(quán)限結(jié)果都返回了)的時(shí)機(jī)一起發(fā)送。
- flatMap() 方法將 Observable<List<Permission>> 轉(zhuǎn)化為 Observable<Boolean>
request(o, permissions);
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 Function<Object, Observable<Permission>>() {
@Override
public Observable<Permission> apply(Object o) throws Exception {
return requestImplementation(permissions);
}
});
}
在 request 這個(gè)方法里面剔蹋,其實(shí) oneOf() 和 pending() 方法我們可以忽略的旅薄,主要的話,我們應(yīng)該關(guān)注 requestImplementation(final String... permissions) 這個(gè)方法泣崩,在這個(gè)方法里面少梁,主要實(shí)現(xiàn)了權(quán)限的請(qǐng)求。
requestImplementation
@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<>();
// 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)) {
// Already granted, or not Android M
// Return a granted Permission object.
// 權(quán)限已經(jīng)被同意或者不是 Android 6.0 以上版本,創(chuàng)建一個(gè) 同意的 Permission 對(duì)象。
list.add(Observable.just(new Permission(permission, true, false)));
continue;
}
if (isRevoked(permission)) {
// 權(quán)限被拒絕崇棠,返回一個(gè) 拒絕的 Permission 對(duì)象。
list.add(Observable.just(new Permission(permission, false, false)));
continue;
}
PublishSubject<Permission> subject = mRxPermissionsFragment.getSubjectByPermission(permission);
// 如果 subject 不存在妨马,那么創(chuàng)建一個(gè) subject挺举。
if (subject == null) {
unrequestedPermissions.add(permission);
subject = PublishSubject.create();
mRxPermissionsFragment.setSubjectForPermission(permission, subject);
}
list.add(subject);
}
// 還未提起申請(qǐng)的權(quán)限進(jìn)行申請(qǐng)
if (!unrequestedPermissions.isEmpty()) {
String[] unrequestedPermissionsArray = unrequestedPermissions.toArray(new String[unrequestedPermissions.size()]);
requestPermissionsFromFragment(unrequestedPermissionsArray);
}
// 嚴(yán)格按照順序發(fā)射數(shù)據(jù)
return Observable.concat(Observable.fromIterable(list));
}
onRequestPermissionsResult()
@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);
}
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;
}
// 發(fā)射權(quán)限申請(qǐng)結(jié)果
mSubjects.remove(permissions[i]);
boolean granted = grantResults[i] == PackageManager.PERMISSION_GRANTED;
subject.onNext(new Permission(permissions[i], granted, shouldShowRequestPermissionRationale[i]));
subject.onComplete();
}
}
RxJava 操作符
Observable.just()
just 操作符是將一個(gè)對(duì)象轉(zhuǎn)化為 Observable 的操作符。這個(gè)對(duì)象可以是一個(gè)數(shù)字烘跺、字符串或者是數(shù)組對(duì)象等湘纵,是 RxJava 中快速創(chuàng)建一個(gè) Observable 對(duì)象的操作符。如果有 subscriber 訂閱的話液荸,那么會(huì)依次調(diào)用 onNext() 和 OnComplete() 方法瞻佛。所以這里只是創(chuàng)建了一個(gè) Observable 對(duì)象,方便后續(xù)的調(diào)用娇钱。
compose(Transformer)操作符
compose 操作符是對(duì) Observable 對(duì)象的整體轉(zhuǎn)化伤柄。例如:通過(guò) Transformer,我們可以將 Observable<Object> 對(duì)象轉(zhuǎn)換成 Observable<Boolean> 對(duì)象了文搂。
public static ObservableTransformer<String,Boolean> getTransformer(){
return new ObservableTransformer<String, Boolean>() {
@Override
public ObservableSource<Boolean> apply(Observable<String> upstream) {
return upstream.flatMap(new Function<String, ObservableSource<Boolean>>() {
@Override
public ObservableSource<Boolean> apply(String s) throws Exception {
return Observable.just(true);
}
});
}
};
}
/**
* 線程切換
* @return
*/
public static <T> ObservableTransformer<T,T> getScheduler(){
return new ObservableTransformer<T, T>() {
@Override
public ObservableSource<T> apply(Observable<T> upstream) {
return upstream.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
};
}
buffer 操作符
buffer 操作符將一個(gè) Observable 變換為另一個(gè)适刀,原來(lái)的 Observable 正常發(fā)射數(shù)據(jù),變換產(chǎn)生的 Observable 發(fā)射這些數(shù)據(jù)的緩存集合煤蹭。buffer將數(shù)據(jù)緩存到一個(gè)集合當(dāng)中笔喉,然后在適當(dāng)?shù)臅r(shí)機(jī)一起發(fā)送。
buffer(count) 以列表(List)的形式發(fā)射非重疊的緩存硝皂,每一個(gè)緩存至多包含來(lái)自原始Observable的count項(xiàng)數(shù)據(jù)(最后發(fā)射的列表數(shù)據(jù)可能少于count項(xiàng))
- 例如:緩存 2 個(gè)數(shù)據(jù)之后常挚,再發(fā)送數(shù)據(jù)(調(diào)用 buffer(count) 函數(shù))
Observable.just(1,2,3,4,5,6)
.buffer(2)
.subscribe(integers -> {
Log.i(TAG, "accept size: "+integers.size());
for (Integer integer : integers) {
Log.i(TAG, "accept: "+integer);
}
});
- 輸出結(jié)果
2018-12-14 11:16:28.452 28126-28126/com.luwei.lwbaselib I/LwBaseActivity: accept size: 2
2018-12-14 11:16:28.452 28126-28126/com.luwei.lwbaselib I/LwBaseActivity: accept: 1
2018-12-14 11:16:28.453 28126-28126/com.luwei.lwbaselib I/LwBaseActivity: accept: 2
2018-12-14 11:16:28.453 28126-28126/com.luwei.lwbaselib I/LwBaseActivity: accept size: 2
2018-12-14 11:16:28.453 28126-28126/com.luwei.lwbaselib I/LwBaseActivity: accept: 3
2018-12-14 11:16:28.453 28126-28126/com.luwei.lwbaselib I/LwBaseActivity: accept: 4
2018-12-14 11:16:28.453 28126-28126/com.luwei.lwbaselib I/LwBaseActivity: accept size: 2
2018-12-14 11:16:28.453 28126-28126/com.luwei.lwbaselib I/LwBaseActivity: accept: 5
2018-12-14 11:16:28.453 28126-28126/com.luwei.lwbaselib I/LwBaseActivity: accept: 6
- 例如:緩存 3 個(gè)數(shù)據(jù),再發(fā)送數(shù)據(jù)稽物,每次移動(dòng) 1 步
Observable.just(1,2,3,4)
.buffer(3,1)
.subscribe(integers -> {
Log.i(TAG, "accept size: "+integers.size());
for (Integer integer : integers) {
Log.i(TAG, "accept: "+integer);
}
});
- 輸出結(jié)果
2018-12-14 11:24:31.455 29164-29164/com.luwei.lwbaselib I/LwBaseActivity: accept size: 3
2018-12-14 11:24:31.455 29164-29164/com.luwei.lwbaselib I/LwBaseActivity: accept: 1
2018-12-14 11:24:31.455 29164-29164/com.luwei.lwbaselib I/LwBaseActivity: accept: 2
2018-12-14 11:24:31.455 29164-29164/com.luwei.lwbaselib I/LwBaseActivity: accept: 3
2018-12-14 11:24:31.455 29164-29164/com.luwei.lwbaselib I/LwBaseActivity: accept size: 3
2018-12-14 11:24:31.455 29164-29164/com.luwei.lwbaselib I/LwBaseActivity: accept: 2
2018-12-14 11:24:31.455 29164-29164/com.luwei.lwbaselib I/LwBaseActivity: accept: 3
2018-12-14 11:24:31.455 29164-29164/com.luwei.lwbaselib I/LwBaseActivity: accept: 4
2018-12-14 11:24:31.456 29164-29164/com.luwei.lwbaselib I/LwBaseActivity: accept size: 2
2018-12-14 11:24:31.456 29164-29164/com.luwei.lwbaselib I/LwBaseActivity: accept: 3
2018-12-14 11:24:31.456 29164-29164/com.luwei.lwbaselib I/LwBaseActivity: accept: 4
2018-12-14 11:24:31.456 29164-29164/com.luwei.lwbaselib I/LwBaseActivity: accept size: 1
2018-12-14 11:24:31.456 29164-29164/com.luwei.lwbaselib I/LwBaseActivity: accept: 4
concat 操作符
是接收若干個(gè)Observables奄毡,發(fā)射數(shù)據(jù)是有序的,不會(huì)交叉贝或。
Subject
- 作為 Observable 和 Observer 之間的橋梁
- 可以當(dāng)做 Observable
- 可以當(dāng)做 Observer
PublishSubject
繼承至 Subject吼过,它的 Observer 只會(huì)接收到 PublishSubject 被訂閱之后發(fā)送的數(shù)據(jù)。示例代碼如下咪奖;我們只會(huì)接收到 publishSubject3 和 publishSubject4盗忱;
PublishSubject<String> publishSubject = PublishSubject.create();
publishSubject.onNext("publishSubject1");
publishSubject.onNext("publishSubject2");
publishSubject.subscribe(new Consumer<String>() {
@Override
public void accept(String s) throws Exception {
Log.i(TAG, "accept: "+s);
}
});
publishSubject.onNext("publishSubject3");
publishSubject.onNext("publishSubject4");
- 執(zhí)行結(jié)果
2018-12-14 11:33:18.168 29916-29916/com.luwei.lwbaselib I/LwBaseActivity: accept: publishSubject3
2018-12-14 11:33:18.168 29916-29916/com.luwei.lwbaselib I/LwBaseActivity: accept: publishSubject4
舉一反三
可以看到,在 RxPermissions 這個(gè)獲取權(quán)限的開(kāi)源框架中羊赵,往 Activity 中添加了一個(gè)空的 Fragment趟佃,這個(gè) fragment 才是用來(lái)發(fā)起申請(qǐng)權(quán)限和處理權(quán)限的請(qǐng)求,最后再將結(jié)果返回昧捷,這樣子就避免了我們發(fā)送請(qǐng)求之后揖闸,還需要在 onRequestPermissionsResult 中進(jìn)行處理,并判斷 requestCode 等繁瑣操作料身。想到這里,我們平時(shí)使用 startActivityForResult 時(shí)衩茸,我們也可以同樣采用這樣的思路來(lái)簡(jiǎn)化我們的請(qǐng)求芹血。
同樣的,我們采用添加空白的 fragment,來(lái)做 startActivityForResult 請(qǐng)求幔烛,主要的實(shí)現(xiàn)類有 SimpleForResult 和 SimpleOnResultFragment啃擦,ActivityResultInfo 是請(qǐng)求 model,接下我們先看代碼饿悬。
SimpleForResult
/**
* @Author: chenjianrun
* @Time: 2018/12/7
* @Description: 避免調(diào)用 startActivity 時(shí)令蛉,需要 onActivityResult 處理的類
*/
public class SimpleForResult {
private static final String TAG = "SimpleForResult";
private SimpleOnResultFragment mSimpleOnResultFragment;
public SimpleForResult(AppCompatActivity activity) {
mSimpleOnResultFragment = getOnResultFragment(activity.getSupportFragmentManager());
}
public SimpleForResult(Fragment fragment){
mSimpleOnResultFragment = getOnResultFragment(fragment.getChildFragmentManager());
}
private SimpleOnResultFragment getOnResultFragment(FragmentManager fragmentManager) {
SimpleOnResultFragment simpleOnResultFragment = findSimpleOnResultFragment(fragmentManager);
if (simpleOnResultFragment == null) {
simpleOnResultFragment = new SimpleOnResultFragment();
fragmentManager
.beginTransaction()
.add(simpleOnResultFragment, TAG)
.commitAllowingStateLoss();
fragmentManager.executePendingTransactions();
}
return simpleOnResultFragment;
}
private SimpleOnResultFragment findSimpleOnResultFragment(FragmentManager fragmentManager) {
return (SimpleOnResultFragment) fragmentManager.findFragmentByTag(TAG);
}
public Observable<ActivityResultInfo> startForResult(Intent intent) {
return mSimpleOnResultFragment.startForResult(intent);
}
public Observable<ActivityResultInfo> startForResult(Class<?> clazz) {
Intent intent = new Intent(mSimpleOnResultFragment.getActivity(), clazz);
return startForResult(intent);
}
public void startForResult(Intent intent, Callback callback) {
mSimpleOnResultFragment.startForResult(intent, callback);
}
public void startForResult(Class<?> clazz, Callback callback) {
Intent intent = new Intent(mSimpleOnResultFragment.getActivity(), clazz);
startForResult(intent, callback);
}
public interface Callback {
void onActivityResult(int requestCode, int resultCode, Intent data);
}
}
SimpleOnResultFragment
/**
* @Author: chenjianrun
* @Time: 2018/12/7
* @Description: 真正調(diào)用 startActivity 和處理 onActivityResult 的類。
*/
public class SimpleOnResultFragment extends Fragment {
private static Map<Integer, PublishSubject<ActivityResultInfo>> mSubjects = new HashMap<>();
private static Map<Integer, SimpleForResult.Callback> mCallbacks = new HashMap<>();
public SimpleOnResultFragment() {
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
public Observable<ActivityResultInfo> startForResult(final Intent intent) {
int requestCode = generateRequestCode();
PublishSubject<ActivityResultInfo> subject = PublishSubject.create();
mSubjects.put(requestCode, subject);
startActivityForResult(intent, requestCode);
return subject;
}
public void startForResult(Intent intent, SimpleForResult.Callback callback) {
int requestCode = generateRequestCode();
mCallbacks.put(requestCode, callback);
startActivityForResult(intent, requestCode);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
//rxjava方式的處理
PublishSubject<ActivityResultInfo> subject = mSubjects.remove(requestCode);
if (subject != null) {
subject.onNext(new ActivityResultInfo(requestCode, resultCode, data));
subject.onComplete();
}
//callback方式的處理
SimpleForResult.Callback callback = mCallbacks.remove(requestCode);
if (callback != null) {
callback.onActivityResult(requestCode, resultCode, data);
}
}
private int generateRequestCode(){
Random random = new Random();
for (;;){
int code = random.nextInt(65536);
if (!mSubjects.containsKey(code) && !mCallbacks.containsKey(code)){
return code;
}
}
}
}
ActivityResultInfo
package com.luwei.util.forresult;
import android.content.Intent;
/**
* @Author: chenjianrun
* @Time: 2018/12/7
* @Description:
*/
public class ActivityResultInfo {
private int requestCode;
private int resultCode;
private Intent data;
public ActivityResultInfo(int requestCode, int resultCode, Intent data) {
this.requestCode = requestCode;
this.resultCode = resultCode;
this.data = data;
}
public int getRequestCode() {
return requestCode;
}
public void setRequestCode(int requestCode) {
this.requestCode = requestCode;
}
public ActivityResultInfo(int resultCode, Intent data) {
this.resultCode = resultCode;
this.data = data;
}
public int getResultCode() {
return resultCode;
}
public void setResultCode(int resultCode) {
this.resultCode = resultCode;
}
public Intent getData() {
return data;
}
public void setData(Intent data) {
this.data = data;
}
}
簡(jiǎn)單使用示例
- 簡(jiǎn)單的 Activity 調(diào)用
// 簡(jiǎn)化調(diào)用 startActivityForResult 及避免在 onActivityResult 中處理繁瑣的結(jié)果
SimpleForResult simpleForResult = new SimpleForResult(this);
simpleForResult.startForResult(ToastActivity.class)
.subscribe((resultInfo) -> {
if (resultInfo.getData() != null) {
ToastUtils.showLong(resultInfo.getData().getStringExtra("result"));
}
});
- 調(diào)用攝像頭
/**
* 打開(kāi)攝像頭
*/
private void openCamera() {
try {
mTmpFile = FileUtils.createTmpFile(this);
} catch (IOException e) {
e.printStackTrace();
}
simpleForResult.startForResult(getOpenCameraIntent(this, mTmpFile))
.subscribe((resultInfo -> {
if (resultInfo.getResultCode() == RESULT_OK) {
mHeadUrl = mTmpFile.getAbsolutePath();
ImageLoaderUtils.loadCircleImage(this, ivHeader, mHeadUrl);
// 裁剪(如果沒(méi)有要求可裁剪狡恬,也可以不要)
startPictureZoom(mTmpFile);
}
}));
}
/**
* 獲取打開(kāi)照相機(jī)的 intent珠叔,適配 Android 7.0
* @param activity
* @param mTmpFile
* @return
*/
public static Intent getOpenCameraIntent(Activity activity,File mTmpFile){
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (intent.resolveActivity(activity.getPackageManager()) != null) {
if (mTmpFile != null && mTmpFile.exists()) {
if (Build.VERSION.SDK_INT >= 24) {
// 適配 Android 7.0
intent.putExtra(MediaStore.EXTRA_OUTPUT,
FileProvider.getUriForFile(activity, activity.getPackageName()+".provider",mTmpFile));
} else {
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mTmpFile));
}
} else {
Toast.makeText(activity, me.nereo.image_selector.R.string.error_image_not_exist, Toast.LENGTH_SHORT).show();
}
} else {
Toast.makeText(activity, me.nereo.image_selector.R.string.msg_no_camera, Toast.LENGTH_SHORT).show();
}
return intent;
}