到底什麼狀況下可使用 RxJava ? 咱們須要知道不是使用 RxJava 而是響應式編程,好吧,那到底何時能夠響應式編程?按道理來說,咱們寫任何代碼均可以採用響應式編程的思想,只不過是有沒有必要而已。羅列一些使用場景:編程
RxView.clicks(mClearContent).debounce(300, TimeUnit.MILLISECONDS)
複製代碼
RxTextView.textChanges(mUserNameEt)
複製代碼
Observable.timer(3, TimeUnit.SECONDS)
複製代碼
Observable.interval(3, 3, TimeUnit.SECONDS)
複製代碼
RxTextView.textChanges(mUserNameEt).debounce(1200, TimeUnit.MILLISECONDS)
複製代碼
rxPermissions.request(Manifest.permission.CAMERA)
複製代碼
####2.RxPermission 源碼分析 上面的用法真的是少得可憐,多是我也用得比較少,其實還有一些如 RxBus + RxRelay,OkHttp + RxJava + Retrofit,MVP + Dragger + RxJava 等等,但這些目前一時半會還講不清楚,但願後面分析完 Retrofit 源碼後能說清楚一些皮毛。咱們仍是老老實實來看看 RxPermission 的源碼?不是說好講使用怎麼又講源碼,爲何非得跟源碼過不去?待會後面你就知道了。先看下使用(申請相機權限):bash
RxPermissions rxPermissions = new RxPermissions(this); rxPermissions.request(Manifest.permission.CAMERA).subscribe(new Consumer<Boolean>() { @Override public void accept(Boolean aBoolean) throws Exception { if(aBoolean){ // 有權限 }else { // 沒權限 } } }); 複製代碼
回想一下咱們在不用任何框架的時候,去申請權限那得多少代碼啊~,關鍵是還須要重載 Activity 的 onRequestPermissionsResult() ,都懷疑人生了。後來本身好不容易寫了個註解權限框架,可是當看到 RxPermission 就棄坑了,看看怎麼實現的:markdown
public Observable<Boolean> request(final String... permissions) { return Observable.just(TRIGGER).compose(ensure(permissions)); } public <T> ObservableTransformer<T, Boolean> ensure(final String... permissions) { return new ObservableTransformer<T, Boolean>() { @Override public ObservableSource<Boolean> apply(Observable<T> o) { return request(o, permissions) // Transform Observable<Permission> to Observable<Boolean> .buffer(permissions.length) .flatMap(new Function<List<Permission>, ObservableSource<Boolean>>() { @Override public ObservableSource<Boolean> apply(List<Permission> permissions) throws Exception { 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(); } // 若是有用戶沒有受權的權限,返回false // Return true if all permissions are granted. for (Permission p : permissions) { if (!p.granted) { return Observable.just(false); } } // 返回受權成功 return Observable.just(true); } }); } }; } @TargetApi(Build.VERSION_CODES.M) private Observable<Permission> requestImplementation(final String... permissions) { // 根據須要申請的權限建立一個 Observable 集合 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. list.add(Observable.just(new Permission(permission, true, false))); continue; } if (isRevoked(permission)) { // Revoked by a policy, return a denied Permission object. 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.fromIterable(list)); } // 調用本身額外建立的 Fragment 的申請權限方法 @TargetApi(Build.VERSION_CODES.M) void requestPermissionsFromFragment(String[] permissions) { mRxPermissionsFragment.log("requestPermissionsFromFragment " + TextUtils.join(", ", permissions)); mRxPermissionsFragment.requestPermissions(permissions); } 複製代碼
源碼其實很簡單,就那麼幾個類,咱們之因此不須要在 Activity 中重寫 onRequestPermissionsResult 方法了,那是由於 RxPermission 本身額外建立了一個 Fragment ,加載到了咱們的 Activity 中,so easy 。架構
####3.RxLogin 庫封裝 最後咱們根據響應式編程的思想,參照 RxPermission 的源碼思想,本身動手來打造一個 RxLogin 第三方登陸框架。我通常都是用友盟第三方的:app
public class UserLoginActivity extends Activity implements UMAuthListener { private UMShareAPI mUmShareAPI; public static final String PLATFORM_KEY = "PLATFORM_KEY"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mUmShareAPI = UMShareAPI.get(this); mUmShareAPI.doOauthVerify(this,SHARE_MEDIA.QQ, this); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); UMShareAPI.get(this).onActivityResult(requestCode, resultCode, data); } @Override public void onStart(SHARE_MEDIA share_media) { } @Override public void onComplete(SHARE_MEDIA share_media, int i, Map<String, String> map) { // 獲取參數用戶信息,調用後臺接口,請求登陸 } @Override public void onError(SHARE_MEDIA share_media, int i, Throwable throwable) { // 獲取等三方帳號信息出錯 } @Override public void onCancel(SHARE_MEDIA share_media, int i) { // 取消第三方登陸 } } 複製代碼
上面這種寫法,咱們初級剛入門的時候通常會這麼寫,這樣寫到底行不行,也不說不行,也不說不對。可是通常咱們不會直接依賴第三方(隔離),並且其實還會多出來不少方法像 onActivityResult() 、onStar()、onCancel() 等等一些咱們可能都不須要或者說不想關注,可是又不得已,哎。框架
下面咱們本身動手寫一個RxLogin,一方面不與第三方的框架直接依賴(隔離),還有一方面咱們過濾掉不關心的方法,還有一方面咱們項目中若是有 Retrofit 、MVP 這些那會更加完美一些,固然還有一些其餘方面。須要額外新建 5 個類,5個類有點多,若是你想放棄:ide
public class RxLogin implements UMAuthListener { private Activity activity; private RxLoginResult mLoginResult; private PublishSubject<RxLoginResult> mLoginEmitter; static UMAuthListener STATIC_LISTENER; private RxLogin(Activity activity){ this.activity = activity; mLoginResult = new RxLoginResult(); STATIC_LISTENER = this; mLoginEmitter = PublishSubject.create(); } public Observable<RxLoginResult> doOauthVerify(final RxLoginPlatform platform) { mShareResult.setPlatform(platform); Intent intent = new Intent(activity,RxLoginActivity.class); intent.putExtra(PLATFORM_KEY,platform); activity.startActivity(intent); activity.overridePendingTransition(0,0); List<Observable<RxLoginResult>> list = new ArrayList<>(1); list.add(mLoginEmitter); return Observable.concat(list); } @Override public void onStart(SHARE_MEDIA share_media) { } @Override public void onComplete(SHARE_MEDIA share_media, int i, Map<String, String> map) { mLoginResult.setIsSucceed(true); mLoginResult.setUserInfo(map); mLoginEmitter.onNext(mLoginResult); } @Override public void onError(SHARE_MEDIA share_media, int i, Throwable throwable) { mLoginResult.setIsSucceed(false); mLoginEmitter.onNext(mLoginResult); throwable.printStackTrace(); } @Override public void onCancel(SHARE_MEDIA share_media, int i) { mLoginResult.setIsSucceed(false); mLoginEmitter.onNext(mLoginResult); } static final SHARE_MEDIA platformChange(RxLoginPlatform platform){ switch (platform){ case Platform_QQ: return SHARE_MEDIA.QQ; case Platform_WX: return SHARE_MEDIA.WEIXIN; } return SHARE_MEDIA.WEIXIN; } public static RxLogin create(Activity activity){ return new RxLogin(activity); } } 複製代碼
看下最後的使用:oop
public class UserLoginActivity extends Activity implements UMAuthListener { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // RxLogin 使用方式以下: RxLogin.create(this) // 第三QQ登陸 .doOauthVerify(RxLoginPlatform.Platform_QQ) .subscribe(new Consumer<RxLoginResult>() { @Override public void accept(RxLoginResult rxLoginResult) throws Exception { if(rxLoginResult.isSucceed()){ // 調用後臺接口,請求登陸 } } }); } } 複製代碼
全部分享大綱:Android進階之旅 - 系統架構篇源碼分析
視頻講解地址:https://pan.baidu.com/s/1pKCrVeFui