RxJava线程切换代替Thread和Handler

作者: 稻田上的稻草人 | 来源:发表于2017-07-09 21:48 被阅读793次

    在我们的日常开发中,我们可能会经常涉及到线程的切换,比如:需要在子线程中加载数据库中的数据,一般情况下,我们会这样做:

     new Thread(new Runnable() {
                @Override
                public void run() {
                    //do something
                }
            }).start();
    

    高效一点的会用线程池来实现。但是有一种情况下是很麻烦的-子线程和主线程有执行顺序或者有交互的时候,这时候我们一般借助Handler机制来实现或者调用Activity的runOnUiThread(new Runnable(){})。但是今天我们来介绍一种利用RxJava实现的主线程、子线程快速切换的方法。

    子线程执行

    定义一个子线程执行的任务接口

    public interface IOTask<T> {
        void doOnIOThread();
    }
    

    在RxScheduler中定义一个在doOnIOThread方法,利用observeOn来切换执行的线程

     public static <T> void doOnIOThread(final IOTask<T> task) {
            Observable.just(task)
                   .observeOn(Schedulers.io())
                    .subscribe(new Action1<IOTask<T>>() {
                        @Override
                        public void call(IOTask<T> tioTask) {
                            tioTask.doOnIOThread();
                        }
                    }, new Action1<Throwable>() {
                        @Override
                        public void call(Throwable throwable) {
                            throwable.printStackTrace();
                        }
                    });
        }
    

    主线程执行

    同理,如果想在主线程中执行时,定义一个任务类接口UITask

    public interface UITask<T> {
        void doOnUIThread();
    }
    

    在RxScheduler中定义一个在doOnUiThread方法:

     public static <T> void doOnUiThread(final UITask<T> task) {
            Observable.just(task)
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Action1<UITask<T>>() {
                        @Override
                        public void call(UITask<T> tuiTask) {
                            task.doOnUIThread();
                        }
                    }, new Action1<Throwable>() {
                        @Override
                        public void call(Throwable throwable) {
                            throwable.printStackTrace();
                        }
                    });
        }
    

    主线程和子线程有交互执行

    这种情况比较复杂些,一般是在子线程中执行完后,需要在主线程中执行一些代码,有着一定的时间顺序关系。但是无论怎么变化,RxJava都能轻松搞定~~

    定义一个任务抽象类Task,其中T表示子线程和主线程需要调用的对象

    public abstract class Task<T> {
        private T t;
    
        public Task(T t) {
            this.t = t;
        }
    
        public void setT(T t) {
            this.t = t;
        }
    
        public T getT() {
            return t;
        }
    
        public abstract void doOnUIThread();
    
        public abstract void doOnIOThread();
    }
    

    RxScheduler类中定义一个doTask方法:

      public static <T> void doTask(final Task<T> task) {
            Observable.create(new Observable.OnSubscribe<T>() {
                @Override
                public void call(Subscriber<? super T> subscriber) {
                    task.doOnIOThread();
                    subscriber.onNext(task.getT());
                    subscriber.onCompleted();
                }
            })
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Action1<T>() {
                        @Override
                        public void call(T t) {
                            task.doOnUIThread();
                        }
                    }, new Action1<Throwable>() {
                        @Override
                        public void call(Throwable throwable) {
                            throwable.printStackTrace();
                        }
                    });
        }
    

    原理很简单,如果你熟悉RxJava的使用的话~

    测试代码

    RxScheduler.doOnIOThread(new IOTask<Void>() {
                @Override
                public void doOnIOThread() {
                 
                    System.out.println("doOnIOThread->" + Thread.currentThread().getName());
                }
            });
    
            RxScheduler.doOnUiThread(new UITask<Void>() {
                @Override
                public void doOnUIThread() {
                
                    System.out.println("doOnUIThread->" + Thread.currentThread().getName());
                }
            });
            final List<String> mData = new ArrayList<>();
            RxScheduler.doTask(new Task<List<String>>(mData) {
                @Override
                public void doOnUIThread() {
                    for (String i : mData) {
                        System.out.println(Thread.currentThread().getName() + "-->" + i);
                    }
                }
    
                @Override
                public void doOnIOThread() {
                    mData.add("java");
                    mData.add("hello");
                    System.out.println(Thread.currentThread().getName() + "-->" + mData.size());
                }
            });
    

    结果如下:

    shiyiliang.me.langelibarysample I/System.out: doOnIOThread->RxIoScheduler-2
    shiyiliang.me.langelibarysample I/System.out: RxIoScheduler-2-->2
    shiyiliang.me.langelibarysample I/System.out: doOnIOThread->main
    shiyiliang.me.langelibarysample I/System.out: main-->java
    shiyiliang.me.langelibarysample I/System.out: main-->hello
    

    是不是比使用Thread或者线程池方便多了,虽然内部底层原理类似,但是后者使用起来就方便多了。

    如果想阅读其他的文章,可以访问我的个人博客Lange的博客

    相关文章

      网友评论

      • 65f3933d18d1:问下博主,RxSchduler是怎么来的?我的RxJava2中没有这个类啊?自己创建的类吗?方便的话能贴个代码吗?

      本文标题:RxJava线程切换代替Thread和Handler

      本文链接:https://www.haomeiwen.com/subject/uqgshxtx.html