协程Flow原理

什么是Flow

Flow直译过来就是“流”的意思,也就是将我们我们任务如同水流一样一步一步分割做处理。想象一下,现在有一个任务需要从山里取水来用你需要怎么做?

  • 扛上扁担走几十里山路把水挑回来。简单粗暴,但是有可能当你走了几十里路发现水干涸了,你就白跑一趟。
  • 架设一条从家到水源之间的水管,以后就可以在家打开水管就有水喝了。如果打开水龙头没水了,那就知道水池没水了,也不用白跑一趟。

这其实就延伸到了目前的两种主流编程思想,响应式和非响应式。

所谓的响应式就是通过订阅、监听的方式等待数据源把数据传递过来。他的优势是可以很方便的与数据源逻辑解耦,并且在数据源可以传递过来之前随意的改变数据流。比如上边例子,我想喝柠檬味的水,那我完全可以在我水龙头上接个柠檬味的管子。而像传统的方案就必须要往水源地加入柠檬精,这时候如果另一个人他想喝西瓜味的水,那就实现不了了。

为什么是Flow

在Flow之前,RXjava一直是我们常用的流式写法,那相比较RXjava,Flow的优势是什么呢?ChatGpt认为有以下几点:

  1. 更加轻量级:Flow 是 Kotlin 标准库的一部分,无需引入额外的依赖库,而 RxJava 需要引入 RxJava 核心库和相关的操作符库,增加了项目的复杂度和体积。
  2. 更加简单:Flow 基于 Kotlin 协程实现,使用协程的语法糖可以实现代码更加简单和易读,比 RxJava 更加简单。
  3. 更加灵活:Flow 支持背压处理和多个订阅者同时订阅同一个数据流,而 RxJava 对于多个订阅者需要使用 share()replay() 等操作符进行处理。
  4. 更加安全:Flow 可以在协程的上下文中运行,因此可以避免 RxJava 中常见的线程安全问题和内存泄漏问题。
  5. 更加可预测:Flow 使用 Kotlin 的类型安全特性,可以更加容易地避免类型不匹配和空指针异常等问题。

其实作为开发人员最关心的就是简洁。越简洁的用法意味着越低廉的学习成本,也更不容易使用出错出现不可以预知的问题。

更多Android开发学习笔记 请点击此处免费领取

传统方案、RXjava、Flow直观对比

我们以一个最常用的例子,子线程网络请求,然后再将数据返回主线程加载UI

传统方案
OkHttpUtils.sendGetRequest("http://example.com", new OkHttpUtils.CallbackListener() {
   
    
    
    @Override
    public void onSuccess(String response) {
   
    
    
        // 在主线程中处理请求成功的结果
        textView.setText(response);
    }
    @Override
    public void onFailure(IOException e) {
   
    
    
        // 在主线程中处理请求失败的结果
        e.printStackTrace();
        Toast.makeText(MainActivity.this, "请求失败", Toast.LENGTH_SHORT).show();
    }
});

发起一个网络请求并注册一个监听,当请求结果回来的时候把结果callback回来。如果此时我们需要网络请求成功之后再去请求第二个接口回来,那我们就需要再嵌套一个callback,就像这样:

OkHttpUtils.sendGetRequest("http://example.com", new OkHttpUtils.CallbackListener() {
   
    
    
    @Override
    public void onSuccess(String response) {
   
    
    
        // 在主线程中处理请求成功的结果
        OkHttpUtils.sendGetRequest("http://example2.com", new OkHttpUtils.CallbackListener() {
   
    
    
            @Override
            public void onSuccess(String response) {
   
    
    
                // 在主线程中处理请求成功的结果
                textView.setText(response);
            }
            @Override
            public void onFailure(IOException e) {
   
    
    
                // 在主线程中处理请求失败的结果
                e.printStackTrace();
                Toast.makeText(MainActivity.this, "请求失败", Toast.LENGTH_SHORT).show();
            }
        });
    }
    @Override
    public void onFailure(IOException e) {
   
    
    
        // 在主线程中处理请求失败的结果
        e.printStackTrace();
        Toast.makeText(MainActivity.this, "请求失败", Toast.LENGTH_SHORT).show();
    }
});

可以看到,当两层的时候我们就完全陷入了“回调地狱”中,逻辑越来越难直观看清。更为致命的是这个方法也无法扩展了。比如说另一个使用者要在第一次请求成功之后弹出一个气泡,第二个使用者说我不需要。这样就只能加参数写if-else判断了。长此以往这个方法就会迅速膨胀再也无法复用,紧接着这个方法的CV1.0、2.0版本就开始“闪亮登场”,最后这个类也无法继续维护了。

RXjava方案
RxJavaUtils.sendGetRequest("http://example.com")
        .subscribe(new Observer<String>() {
   
    
    
            @Override
            public void onSubscribe(Disposable d) {
   
    
    
                // 在这里可以做一些准备工作,比如显示进度条等
            }
            @Override
            public void onNext(String response) {
   
    
    
                // 在主线程中处理请求成功的结果
                textView.setText(response);
            }
            @Override
            public void onError(Throwable e) {
   
    
    
                // 在主线程中处理请求失败的结果
                e.printStackTrace();
                Toast.makeText(MainActivity.this, "请求失败", Toast.LENGTH_SHORT
           })

猜你喜欢

转载自blog.csdn.net/m0_70748458/article/details/130626056