IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> LoadingTransformer:利用RxJava优雅显示隐藏加载对话框 -> 正文阅读

[移动开发]LoadingTransformer:利用RxJava优雅显示隐藏加载对话框

从事Android开发过程中,我们经常要在网络请求的时候显示“加载中”或“请求中”的对话框,然后在请求结束时显示对应状态或隐藏对话框,而手动关闭对话框时又要取消加载。相信类似需求应该经常碰到,有时候一个项目中会有好几个这样的地方,如果每个地方都要实现一遍类似的功能,那也是一件很郁闷的事。本文就展示一种通过增加一行代码来处理这种需求的工具–LoadingTransformer

1. 示例

首先来看一个示例:

Observable
        .fromCallable(() -> {
            Log.d(TAG, "test loading: ");
            Thread.sleep(3000);              //模拟长时间请求
            return 1;
        })
        .subscribeOn(Schedulers.io())
        .compose(new LoadingTransformer<>(context, "加载中..."))
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(i -> {
            //处理结果
        }, throwable -> {
            //处理异常
        });

这里用sleep来模拟长时间请求,通过添加一行compose(new LoadingTransformer<>(context, "加载中..."))来实现加载过程中显示对话框,当加载完成的时候对话框消失。

在来看第二个示例:

Observable
        .fromCallable(() -> {
            Log.d(TAG, "test loading: ");
            Thread.sleep(3000);         //模拟长时间请求
            if (new Random().nextBoolean()) {//随机出错,模拟异常情况
                throw new RuntimeException("something wrong!");
            }
            return 1;
        })
        .subscribeOn(Schedulers.io())
        .compose(new LoadingTransformer<>(view.getContext(), "加载中...", "加载失败", "加载结束"))
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(i -> {
            //处理结果
        }, throwable -> {
            //处理异常
        });

这里我们给LoadingTransformer提供了三个参数,分别表示加载中的文案、加载失败的文案以及加载结束的文案,这样对话框就会在对应的状态显示对应的内容。

2. LoadingTransformer的实现

import android.content.Context;

import androidx.appcompat.app.AlertDialog;

import org.reactivestreams.Publisher;

import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.annotations.NonNull;
import io.reactivex.rxjava3.core.Completable;
import io.reactivex.rxjava3.core.CompletableSource;
import io.reactivex.rxjava3.core.CompletableTransformer;
import io.reactivex.rxjava3.core.Flowable;
import io.reactivex.rxjava3.core.FlowableTransformer;
import io.reactivex.rxjava3.core.Maybe;
import io.reactivex.rxjava3.core.MaybeSource;
import io.reactivex.rxjava3.core.MaybeTransformer;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.core.ObservableSource;
import io.reactivex.rxjava3.core.ObservableTransformer;
import io.reactivex.rxjava3.core.Single;
import io.reactivex.rxjava3.core.SingleSource;
import io.reactivex.rxjava3.core.SingleTransformer;
import io.reactivex.rxjava3.disposables.Disposable;

public class LoadingTransformer<T> implements ObservableTransformer<T, T>,
        SingleTransformer<T, T>,
        MaybeTransformer<T, T>,
        FlowableTransformer<T, T>,
        CompletableTransformer {  //实现了RxJava的各种Transformer,方便使用

    private final AlertDialog dialog; //处于演示目的,使用AlertDialog,实际中用对应自定义弹窗替代
    private String errorMsg;
    private String completeMsg;

    public LoadingTransformer(Context context, String s) {
        dialog = new AlertDialog.Builder(context).setMessage(s).setCancelable(true).create();
    }

    public LoadingTransformer(Context context, String s, String errorMsg) {
        dialog = new AlertDialog.Builder(context).setMessage(s).setCancelable(true).create();
        this.errorMsg = errorMsg;
    }

    public LoadingTransformer(Context context, String s, String errorMsg, String completeMsg) {
        dialog = new AlertDialog.Builder(context).setMessage(s).setCancelable(true).create();
        this.errorMsg = errorMsg;
        this.completeMsg = completeMsg;
    }

    private void onComplete() {
        if (Objects.nonNull(completeMsg)) {
            dialog.setMessage(completeMsg);
        } else {
            if (dialog.isShowing()) {
                dialog.dismiss();
            }
        }
    }

    private void onError(Throwable t) {
        if (Objects.nonNull(errorMsg)) {
            dialog.setMessage(errorMsg);
        } else {
            if (dialog.isShowing()) {
                dialog.dismiss();
            }
        }
    }

    @Override
    public @NonNull CompletableSource apply(@NonNull Completable upstream) {
        return upstream
                .observeOn(AndroidSchedulers.mainThread())
                .doOnSubscribe(d -> dialog.setOnDismissListener(dialogInterface -> d.dispose()))
                .doOnSubscribe((Disposable d) -> dialog.show())
                .doOnComplete(this::onComplete)
                .doOnError(this::onError);
    }

    @Override
    public @NonNull MaybeSource<T> apply(@NonNull Maybe<T> upstream) {
        return upstream
                .observeOn(AndroidSchedulers.mainThread())
                .doOnSubscribe(d -> dialog.setOnDismissListener(dialogInterface -> d.dispose()))
                .doOnSubscribe(d -> dialog.show())
                .doOnComplete(this::onComplete)
                .doOnError(this::onError);
    }

    @Override
    public @NonNull ObservableSource<T> apply(@NonNull Observable<T> upstream) {
        return upstream
                .observeOn(AndroidSchedulers.mainThread())
                .doOnSubscribe(d -> dialog.setOnDismissListener(dialogInterface -> d.dispose()))
                .doOnSubscribe(d -> dialog.show())
                .doOnComplete(this::onComplete)
                .doOnError(this::onError);
    }

    @Override
    public @NonNull SingleSource<T> apply(@NonNull Single<T> upstream) {
        return upstream
                .observeOn(AndroidSchedulers.mainThread())
                .doOnSubscribe(d -> dialog.setOnDismissListener(dialogInterface -> d.dispose()))
                .doOnSubscribe(d -> dialog.show())
                .doOnSuccess(t -> onComplete())
                .doOnError(this::onError);
    }

    @Override
    public @NonNull Publisher<T> apply(@NonNull Flowable<T> upstream) {
        return upstream
                .observeOn(AndroidSchedulers.mainThread())
                .doOnSubscribe(subscription -> dialog.setOnDismissListener(dialogInterface -> subscription.cancel()))
                .doOnSubscribe(subscription -> dialog.show())
                .doOnComplete(this::onComplete)
                .doOnError(this::onError);
    }
}

3. 注意

  1. 调用Dialog的setOnDismissListener方法时注意避免重复设置导致覆盖的情况,只设置一次就好。
  2. 如果要根据网络返回的结果(比如状态码)来提示异常,可以在doOnSuccessdoOnNext中对结果进行判断并对应信息。
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-04-26 11:52:02  更:2022-04-26 11:52:13 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 0:00:34-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码