RxActivityResult 突破固有思惟,获取 onActivityResult 数据

学习契机

接触 RxJava 有一段时间了,但总感受对于 RxJava 的使用和理解还在入门阶段。一方面和本身没有去深刻学习有关,觉得使用了一些基础的操做符,就敢吹牛说本身掌握 RxJava。另外一方面对RxJava 事件驱动型 的编程思想,笔者始终领悟的很差。java

我认为单纯的学习操做符,实际意义不大。事实上,笔者以前也花费了大量的时间学习操做符,到头来发现效果不佳,由于我仍是不知道什么时候,该正确的去使用 RxJava 操做符。我便向朋友请教,他说你能够试着去阅读一些 Rx 开源项目的源码,从简单的入手,去学习 Rx 带来的便利,和思惟方式的改变。react

又是这位朋友,向我推荐了 RxActivityResult。代码量很少,很适合我学习。下面,让咱们换种方式,去 startActiviityForResult()git

简介

RxActivityResultVictorAlbertos 大神的又一个 Rx 开源力做,该库不久前的更新,现已全面支持 AndroidX。当你已经受够了,从 onActivityResult() 中接受来自系统(如相机),或者本身的回调数据,不妨尝试下这个库,让你今后告别 onActivityResult()。简单介绍下这个库的特色:github

  • 传入 ActivityFragment 的有效实例,就能够在任何类开启一个 Intent
  • 数据被封装在一个可观察的 Observable 中返回,意味着能够继续享受RxJava 操做符的便利。

使用

  1. 首先在 Project 下的 build.gradle 添加 maven 依赖。
allprojects {
    repositories {
        google()
        jcenter()
        maven { url "https://jitpack.io" }
    }
}
复制代码
  1. 在 app 下的 build.gradle 添加 RxActivityResultRxJava 的依赖。
implementation 'com.github.VictorAlbertos:RxActivityResult:0.5.0-2.x'
implementation 'io.reactivex.rxjava2:rxjava:2.2.3'
复制代码
  1. 添加完依赖,咱们须要在 Application 中注册 RxActivityResult
class MyApp : Application() {

    override fun onCreate() {
        super.onCreate()
        RxActivityResult.register(this)
    }
}
复制代码
  1. MainActivity 中经过点击按钮,跳转至 Main2Activity。如下是代码示例
@SuppressLint("CheckResult")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val intent = Intent(this, Main2Activity::class.java)
        btnJump
            .setOnClickListener {
                RxActivityResult
                    .on(this)
                    .startIntent(intent)
                    .map {
                        it.data()
                    }
                    .subscribe {
                        val extra = it.getStringExtra("resultData")
                        println(extra)
                    }
            }
    }
复制代码
  1. Main2Activity 中,点击按钮回传数据。
override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main2)
        btnResult.setOnClickListener {
            val intent = intent
            intent.putExtra("resultData", "我是回传的数据")
            setResult(Activity.RESULT_OK, intent)
            finish()
        }
    }
复制代码

ok,到此一个简单的使用就完成了。若是搭配 RxBinding 使用,可以让本身的代码更加 Rx,保证这一系列操做事件流的完整性。编程

btnJump
            .clicks()
            .throttleFirst(500, TimeUnit.MILLISECONDS)
            .map { Intent(this, Main2Activity::class.java) }
            .flatMap {
                RxActivityResult.on(this)
                    .startIntent(it)
            }
            .map{ it.data() }
            .subscribe {
                val stringExtra = it.getStringExtra("resultData")
                println(stringExtra)
            }
复制代码

经过寥寥的几行代码,便告别了 onActivityResult(),而且能够接收到返回的数据。这里先抛出两个问题:app

  • Application 中为啥要注册。
  • onActivityResult() 的具体实现是谁。

源码分析

  1. 首先咱们看下 Application 中的注册。
class MyApp:Application() {

    override fun onCreate() {
        super.onCreate()
        RxActivityResult.register(this)
    }
}
复制代码

先简单介绍下 ActivityLifecycleCallbacks,它是定义在 Application 中的一个接口,能够用来监听全部 Activity 生命周期的回调,而且优先于 Activity 生命周期的回调。使用 ActivityLifecycleCallbacks 也能够判断当前 App 处于前台仍是后台。具体的使用请自行查阅。maven

RxActivityResult.register() 其实返回的是库做者定义的 ActivitiesLifecycleCallbacks 类。经过查看源码得知,使用了传入的 Application 对象去注册监听 Activity 的生命周期。ide

到如今也就能够回答提出的第一个问题,在 Application 中注册 RxActivityResult,是为了能够监听到全部 Activity 的生命周期。毕竟在 onPause 以后去 startIntent() ,是没有意义的。源码分析

  1. 接着看下 Activity 中的具体使用
RxActivityResult
                    .on(this) // 步骤 1
                    .startIntent(intent) // 步骤 2
                    .map { it.data }
                    .subscribe {
                        val extra = it.getStringExtra("resultData")
                        println(extra)
                    }
复制代码
  • 调用 on() 传入的 this 对象,用于判断用户是从 Activity 或者 Fragment 的操做
  • startIntent() 方法,最终会调用 startHolderActivity()
@SuppressLint("CheckResult")
        private Observable<Result<T>> startHolderActivity(Request request, @Nullable OnPreResult onPreResult) {

            OnResult onResult = uiTargetActivity ? onResultActivity() : onResultFragment(); // 判断从 Activity 或者 Fragment 启动的 Intent
            request.setOnResult(onResult);
            request.setOnPreResult(onPreResult);
        
            // 设置请求对象
            HolderActivity.setRequest(request);

            // 从当前 Activity ,打开 HolderActivity 
            activitiesLifecycle.getOLiveActivity().subscribe(new Consumer<Activity>() {
                @Override
                public void accept(Activity activity) throws Exception {
                    activity.startActivity(new Intent(activity, HolderActivity.class)
                            .addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION));
                }
            });
          
            // 返回 PublishSubject
            return subject;
        }
复制代码

先看下 onResultActivity()学习

private OnResult onResultActivity() {
            return new OnResult() {
                @Override
                public void response(int requestCode, int resultCode, Intent data) {
                    if (activitiesLifecycle.getLiveActivity() == null) return;

                    //If true it means some other activity has been stacked as a secondary process.
                    //Wait until the current activity be the target activity
                    if (activitiesLifecycle.getLiveActivity().getClass() != clazz) {
                        return;
                    }

                    T activity = (T) activitiesLifecycle.getLiveActivity();
                  // 发射 Result 结果
                    subject.onNext(new Result<>(activity, requestCode, resultCode, data));
                    subject.onComplete();
                }

                @Override
                public void error(Throwable throwable) {
                    subject.onError(throwable);
                }
            };
        }
复制代码

建立一个 OnResult 对象,而且在 response() 中发射 Result 结果。

  • Subject Subject 既能够是数据源 Observable,也能够是数据的订阅者 Observer
public abstract class Subject<T> extends Observable<T> implements Observer<T> {
    ...
}
复制代码

经过查看源码能够看到,Subject 实际上仍是 Observable,只不过它实现了 Observer接口,能够经过 onNextonCompleteonError 方法发射和终止发射数据。做者在发射 Result 的时候,使用了 PublischSubjectPublischSubject 的特色是: Observer 只接受被订阅以后发射的数据。

  1. 看下 HolderActivity 中的操做
  • onCreate() 中打开真正的 Intent对象

  • onActivityResult 中关闭 HolderActivity,而且在 onDestroy 回传数据

@Override
    protected void onDestroy() {
        super.onDestroy();
        if (onResult != null)
            onResult.response(requestCode, resultCode, data);
    }
复制代码

总结下大致的逻辑,比如咱们购物的流程,从京东下单买书 (startActivityForResult),店主交待员工小王(HoldrActivity)去仓库查找书籍,并打包发送快递(PublischSubject.onNext(Result()))。快递员送货上门,顾客核对购买的信息(intent.getStringExtra("resultData")),信息无误的话获取购买的书籍。

总结与思考

经过对 RxActivityResult 库的简单分析,了解了 ActivityLifecycleCallbacksPublischSubject 在三方库中的具体使用。也认识了一些 RxJava 的操做符,如 takeWhile 过滤操做符。更重要的是,在没有碰见 RxActivityResult 时,笔者一般都是循序渐进的在 onActivityResult() 中获取数据,而做者的这种方式,打破了我以前的认识,原来还能够这样处理 onActivityResult() 数据。

当我对目前这种学习方式(使用-源码分析-总结),所带来的收获沾沾自喜的时候。朋友的一番话,又警醒了我。阅读源码,只是进阶的第一步。更重要的是,对思想的掌握,站在更高的角度去思考,为何这样设计。而不该该只知足于基础的源码分析,背后的设计思想才是精髓。

若是只是对源码进行分析,按照做者的思路去拨开云雾,获得的进步是有限的。须要再进一步的 思考,这将是我接下来须要学习的地方。

相关文章
相关标签/搜索