RxJava应用

本文介绍了RxJava3.X如何进行线程控制,包括内置的Scheduler和subscribeOn/observeOn操作符的使用。示例展示了如何结合OkHttp和Retrofit在不同线程中执行网络请求,以及如何实现事件总线RxBus进行事件传递。
摘要由CSDN通过智能技术生成

8.4 RxJava3.X 的线程控制

1. 内置的Scheduler

  • 如果我们不指定线程,则默认是在调用subscribe方法的线程上进行回调。
  • 如果我们想要切换的话,就会用到Scheduler。
  • 下面是RxJava几个内置的Scheduler(调度器)
    在这里插入图片描述

2. 控制线程

  • 在RxJava中使用subscribeOn和observeOn操作符可以来控制线程。 使用方法详情见前面笔记。

RxJava 3.x 结合OkHttp访问网络

1. 首先创建Observable

  • 根据OkHttp请求的回调,来定义事件的规则
OkHttpClient mOkHttpClient;
private Observable<String> getObservable(final String ip){
    Observable observable = Observable.create(new ObservableOnSubscribe<String>() {
        @Override
        public void subscribe(@NonNull ObservableEmitter<String> emitter) throws Throwable {
            mOkHttpClient = new OkHttpClient();
            Request request = new Request.Builder()
                    .url("http://www.baidu.com")
                    .build();
            Call call = mOkHttpClient.newCall(request);
            call.enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    emitter.onError(new Exception("error"));
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    String str = response.body().string();
                    //调用emitter.onNext将请求返回的数据添加到事件队列中
                    emitter.onNext(str);
                    emitter.onComplete();
                }
            });
        }
    });

    return observable;
}

2. 实现观察者

  • 将发射事件的线程切换到io线程,然后将访问网络的回调设置回主线程,所以可以正常显示Toast。
  • RxJava也解决了OkHttp的回调不在主线程的问题。
  • 然后我们通过postAsynHttp方法传入ip的值就可以
private String TAG = "Ning";
private void postAsynHttp(String size){

    getObservable(size).subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Observer<String>() {
                @Override
                public void onSubscribe(@NonNull Disposable d) {

                }

                @Override
                public void onNext(@NonNull String s) {
                    Log.d(TAG, "onNext: " + s);
                    Toast.makeText( getApplicationContext() , "请求成功", Toast.LENGTH_SHORT ).show();
                }

                @Override
                public void onError(@NonNull Throwable e) {
                    Log.d(TAG, "onError: " + e.getMessage());
                }

                @Override
                public void onComplete() {
                    Log.d(TAG, "onComplete");
                }
            });
}

在这里插入图片描述

RxJava3.X 结合Retrofit访问网络

1. 配置gradle

implementation 'io.reactivex.rxjava3:rxandroid:3.0.2'
implementation 'io.reactivex.rxjava3:rxjava:3.1.5'
implementation 'com.squareup.retrofit2:retrofit:2.7.0'
implementation 'com.squareup.retrofit2:converter-gson:2.7.0'
//这个依赖别忘了导
implementation 'com.squareup.retrofit2:adapter-rxjava3:2.9.0'

2. 返回类的设置

package com.example.rxjava;

public class User {
    private String name;
    private int followers;

    public String getName(){
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setFollowers(int followers) {
        this.followers = followers;
    }

    public int getFollowers() {
        return followers;
    }
}

3. 网络接口

package com.example.rxjava;

import io.reactivex.rxjava3.core.Single;
import retrofit2.http.GET;
import retrofit2.http.Path;

public interface IpServiceForPost {
    @GET("users/{user}")
    Single<User> getUser(@Path("user") String userId);
}

4. 创建Retrofit

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("http://api.github.com/")
        .addConverterFactory(GsonConverterFactory.create())
        .addCallAdapterFactory(RxJava3CallAdapterFactory.create())
        .build();

5. 动态代理接口对象

IpServiceForPost ipServiceForPost = retrofit.create(IpServiceForPost.class);

6. 订阅处理结果

ipServiceForPost.getUser("octocat")
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new SingleObserver<User>() {
            @Override
            public void onSubscribe(@NonNull Disposable d) {
                //订阅时回调这里可以显示加载框等操作
            }

            @Override
            public void onSuccess(@NonNull User user) {
                Log.d(TAG, "onSuccess: " + user.getName() + "   " + user.getFollowers() );
            }

            @Override
            public void onError(@NonNull Throwable e) {
                Log.d(TAG, "onError: ");
            }
        });

在这里插入图片描述

补充

  • 一个界面可能会有多个请求,对于每个请求来说,我们都会在onSubscribe方法中将Disposable添加到compositeDisposables中。
  • 调用compositeDisposables的clear方法时,会取消所有的请求。

RxJava3.x 实现RxBus

  • 通过RxJava来实现事件总线RxBus。用来替代EventBus和otto

1. 创建RxBus

  • 首先创建RxBus,这里的RxBus只支持基本的功能
package com.example.rxjava;


import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.subjects.PublishSubject;
import io.reactivex.rxjava3.subjects.Subject;

public class RxBus {
    private final Subject<Object> subject;
    private static volatile RxBus rxBus;
    
    //Subject是非线程安全的,所有在这里将PublishSubject转化为一个SerializedSubject
    private RxBus(){
        subject = PublishSubject.create().toSerialized();
    }
    
    //注释2处用到了单例模式的双重检查模式
    public static RxBus getInstance(){
        if(rxBus == null){
            synchronized (RxBus.class){
                if(rxBus == null){
                    rxBus = new RxBus();
                }
            }
        }
        return rxBus;
    }
    
    public void post(Object ob){
        subject.onNext(ob);
    }
    
    //ofType只会发送指定的数据
    public <T>Observable<T> toObservable(Class<T> eventType){
        return subject.ofType(eventType);
    }
    
}
  • ofType的源码
  • ofType的源码使用了filter操作符和cast操作符。
  • 通过filter来判定是不是指定类型的数据,如果不是指定类型的数据,就不会交给订阅者。
  • 通过cast操作符来将Observable转化成指定类型的Observable
public final <@NonNull U> Observable<U> ofType(@NonNull Class<U> clazz) {
    Objects.requireNonNull(clazz, "clazz is null");
    return filter(Functions.isInstanceOf(clazz)).cast(clazz);
}

2. 事件类

package com.example.rxjava;

public class MessageEvent {
    private String message;
    public MessageEvent(String message){
        this.message = message;
    }

    public String getMessage(){
        return message;
    }

    public void setMessage(String message){
        this.message = message;
    }
    
}

3. 发送事件

  • 我们在RxBusActivity定义了一个Button,点击这个Button的时候就会发送事件。
package com.example.rxjava;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class RxBusActivity extends AppCompatActivity {
    private Button bt_post;
    private TextView bt_text;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_rx_bus);
        bt_post = (Button) this.findViewById(R.id.bt_post);
        bt_text = this.findViewById(R.id.bt_text);
        
        bt_post.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                RxBus.getInstance().post(new MessageEvent("用RxJava实现RxBus"));
            }
        });

    }
}

4. 接收事件

RxBus.getInstance()
        .toObservable(MessageEvent.class)
        .subscribe(new Observer<MessageEvent>() {
            @Override
            public void onSubscribe(@NonNull Disposable d) {

            }

            @Override
            public void onNext(@NonNull MessageEvent messageEvent) {
                if (messageEvent != null) {
                   bt_text.setText(messageEvent.getMessage());
                }
            }

            @Override
            public void onError(@NonNull Throwable e) {
                bt_text.setText("error!");
            }

            @Override
            public void onComplete() {

            }
        });

在这里插入图片描述

5. 取消订阅事件

  • 取消订阅事件,防止内存泄露
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值