RxJava 多线程控制

第一次写博客,如果写的不好希望大家理解。


  在了解rxjava的多线程的,我们先来一个单线程下载网络图片并显示progress的。

先贴出代码:

@Override
public void onClick(View v) {
     final ProgressDialog pd = new ProgressDialog(this);
    Observable.create(new Observable.OnSubscribe<String>() {
        @Override
        public void call(Subscriber<? super String> subscriber) {
            subscriber.onNext("http://img1.imgtn.bdimg.com/it/u=1225257463,1229468910&fm=21&gp=0.jpg");
            subscriber.onCompleted();
        }
    })
            .subscribeOn(Schedulers.io())
            .doOnSubscribe(new Action0() {
                @Override
                public void call() {
                    pd.show();
                }
            })
            .subscribeOn(AndroidSchedulers.mainThread())
            .map(new Func1<String, Bitmap>() {
                @Override
                public Bitmap call(String s) {
                    return getImageBitmap(s);
                }
            })
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber<Bitmap>() {
                @Override
                public void onCompleted() {
                    if (pd.isShowing()) {
                        pd.dismiss();
                    }
                }

                @Override
                public void onError(Throwable e) {
                    if (pd.isShowing()) {
                        pd.dismiss();
                    }
                }

                @Override
                public void onNext(Bitmap bitmap) {
                    iv1.setImageBitmap(bitmap);
                }
            });
}

private Bitmap getImageBitmap(String url){
    URL imgUrl = null;
    Bitmap bitmap = null;
    try {
        imgUrl = new URL(url);
        HttpURLConnection conn = (HttpURLConnection)imgUrl.openConnection();
        conn.setDoInput(true);
        conn.connect();
        InputStream is = conn.getInputStream();
        bitmap = BitmapFactory.decodeStream(is);
        is.close();
    } catch (MalformedURLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }catch(IOException e){
        e.printStackTrace();
    }
    return bitmap;
}

上面代码其实不难理解,下面简单解释一下:

rxjava主要需要理解两个概念:观察者(Observer)和被观察者(Observable),RxJava 的异步实现,是通过一种扩展的观察者模式来实现的。观察者和被观察者通过订阅(Subscribe)关系建立联系的。 

    

  我们看看以上的代码的异步是怎么实现的。答案是通过subscribeOn(Schedulers.io())这句话实现的。

Schedulers.io();是rxjava自己提供的线程调度器,用来读写文件、读写数据库、网络信息交互等。rxjava还

Schedulers.immediate();Schedulers.newThread();Schedulers.computation();等。对此我就不做过多的解释了。这里我

特别提一下AndroidSchedulers.mainThread()这个是rxandroid提供的android的ui线程。

  

   也许有人会问为什么会有2个subscribeOn();其中第二是作用在doOnSubscribe()方法上的,让doOnSubscribe运


行在ui线程上。Observable.doOnSubscribe()是在Subscribe发生后而且在事件发送前执行的,所以他是可以指定线程

的。

  最后使用observeOn(AndroidSchelers.mainThread())指定观察者运行ui线程,所以我可以在onNext()中设置

ImageView的图片,在onError和onCompleted中隐藏progress。


  好了,上面简单讲了一下一个线程下载图片,并在主线程设置图片了,我们来谈论下多线程并行运行下载图片,

并且将它在imageview显示出来。而且在图片都下载完了之后弹出一个土司告知用户。

先贴一种实现方式的代码:

private void moreThread() {
    final ProgressDialog pd = new ProgressDialog(this);
    Observable
            .just("http://img1.imgtn.bdimg.com/it/u=1225257463,1229468910&fm=21&gp=0.jpg")
            .map(new Func1<String, Map<Integer, Bitmap>>() {
                @Override
                public Map<Integer, Bitmap> call(String s) {
                    Map<Integer, Bitmap> map = new HashMap<Integer, Bitmap>();
                    map.put(1, getImageBitmap(s));
                    return map;
                }
            })
            .subscribeOn(Schedulers.io())
            .mergeWith(Observable.just("http://pic1a.nipic.com/2008-11-26/200811268173650_2.jpg")
                    .map(new Func1<String, Map<Integer, Bitmap>>() {
                        @Override
                        public Map<Integer, Bitmap> call(String s) {
                            Map<Integer, Bitmap> map = new HashMap<Integer, Bitmap>();
                            map.put(2, getImageBitmap(s));
                            return map;
                        }
                    }).subscribeOn(Schedulers.io()))
            .mergeWith(Observable
                    .just("http://pic13.nipic.com/20110415/1347158_132411659346_2.jpg")
                    .map(new Func1<String, Map<Integer, Bitmap>>() {
                        @Override
                        public Map<Integer, Bitmap> call(String s) {
                            Map<Integer, Bitmap> map = new HashMap<Integer, Bitmap>();
                            map.put(3, getImageBitmap(s));
                            return map;
                        }
                    }).subscribeOn(Schedulers.io()))
            .mergeWith(Observable
                    .just("http://img4.3lian.com/sucai/img6/230/29.jpg")
                    .map(new Func1<String, Map<Integer, Bitmap>>() {
                        @Override
                        public Map<Integer, Bitmap> call(String s) {
                            Map<Integer, Bitmap> map = new HashMap<Integer, Bitmap>();
                            map.put(4, getImageBitmap(s));
                            return map;
                        }
                    }).subscribeOn(Schedulers.io()))
            .mergeWith(Observable
                    .just("http://img1.imgtn.bdimg.com/it/u=2493205512,407054761&fm=21&gp=0.jpg")
                    .map(new Func1<String, Map<Integer, Bitmap>>() {
                        @Override
                        public Map<Integer, Bitmap> call(String s) {
                            Map<Integer, Bitmap> map = new HashMap<Integer, Bitmap>();
                            map.put(5, getImageBitmap(s));
                            return map;
                        }
                    }).subscribeOn(Schedulers.io()))
            .doOnSubscribe(new Action0() {
                @Override
                public void call() {
                    pd.show();
                }
            })
            .subscribeOn(AndroidSchedulers.mainThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber<Map<Integer, Bitmap>>() {
                @Override
                public void onCompleted() {
                    if (pd.isShowing()) {
                        pd.dismiss();
                    }
                    Toast.makeText(SiyActivity.this,"5张图片下载完毕",0).show();
                }

                @Override
                public void onError(Throwable e) {
                    if (pd.isShowing()) {
                        pd.dismiss();
                    }
                }

                @Override
                public void onNext(Map<Integer, Bitmap> integerBitmapMap) {
                    Set<Integer> set = integerBitmapMap.keySet();

                    for (Integer key : set) {
                        switch (key) {
                            case 1:
                                iv1.setImageBitmap(integerBitmapMap.get(1));
                                break;
                            case 2:
                                iv2.setImageBitmap(integerBitmapMap.get(2));
                                break;
                            case 3:
                                iv3.setImageBitmap(integerBitmapMap.get(3));
                                break;
                            case 4:
                                iv4.setImageBitmap(integerBitmapMap.get(4));
                                break;
                            case 5:
                                iv5.setImageBitmap(integerBitmapMap.get(5));
                                break;
                        }

                    }
                }
            });

}

  代码比较长但是逻辑并不复杂。

  下面我们慢慢看并解释。首先我们得搞明白同步下载5张图片需要5个observable,因为当使用了多个

subscribeOn() 的时候,只有第一个 subscribeOn() 起作用,所以我们不能在同一observable上多次指定被观察者的线

程。还有就是我们使用了3个操作符。just()可以简化我们observable的创建,map() 方法将参数中的 String 对象转换成一个 Bitmap 对象后回,mergeWith()

操作符,两个或更多同类型的 Observable 可以合并到一起去创建一个 Observable,最后指定合并后的Observable

的观察者在ui线程设置图片,弹出土司。


  再给一种实现方式:

private void moreThread_2(){
    final ProgressDialog pd = new ProgressDialog(SiyActivity.this);
    Single.merge(Single.create(new Single.OnSubscribe<String>() {
                @Override
                public void call(SingleSubscriber<? super String> singleSubscriber) {
                    singleSubscriber.onSuccess("http://img1.imgtn.bdimg.com/it/u=1225257463,1229468910&fm=21&gp=0.jpg");
                }
            }).map(new Func1<String, Map<Integer, Bitmap>>() {
                @Override
                public Map<Integer, Bitmap> call(String s) {
                    Map<Integer, Bitmap> map = new HashMap<Integer, Bitmap>();
                    map.put(1, getImageBitmap(s));
                    return map;
                }
            }).subscribeOn(Schedulers.io()),
            Single.create(new Single.OnSubscribe<String>() {
                @Override
                public void call(SingleSubscriber<? super String> singleSubscriber) {
                    singleSubscriber.onSuccess("http://pic1a.nipic.com/2008-11-26/200811268173650_2.jpg");
                }
            }).map(new Func1<String, Map<Integer, Bitmap>>() {
                @Override
                public Map<Integer, Bitmap> call(String s) {
                    Map<Integer, Bitmap> map = new HashMap<Integer, Bitmap>();
                    map.put(2, getImageBitmap(s));
                    return map;
                }
            }).subscribeOn(Schedulers.io()),
            Single.create(new Single.OnSubscribe<String>() {
                @Override
                public void call(SingleSubscriber<? super String> singleSubscriber) {
                    singleSubscriber.onSuccess("http://pic13.nipic.com/20110415/1347158_132411659346_2.jpg");
                }
            }).map(new Func1<String, Map<Integer, Bitmap>>() {
                @Override
                public Map<Integer, Bitmap> call(String s) {
                    Map<Integer, Bitmap> map = new HashMap<Integer, Bitmap>();
                    map.put(3, getImageBitmap(s));
                    return map;
                }
            }).subscribeOn(Schedulers.io()),
            Single.create(new Single.OnSubscribe<String>() {
                @Override
                public void call(SingleSubscriber<? super String> singleSubscriber) {
                    singleSubscriber.onSuccess("http://img4.3lian.com/sucai/img6/230/29.jpg");
                }
            }).map(new Func1<String, Map<Integer, Bitmap>>() {
                @Override
                public Map<Integer, Bitmap> call(String s) {
                    Map<Integer, Bitmap> map = new HashMap<Integer, Bitmap>();
                    map.put(4, getImageBitmap(s));
                    return map;
                }
            }).subscribeOn(Schedulers.io()),
            Single.create(new Single.OnSubscribe<String>() {
                @Override
                public void call(SingleSubscriber<? super String> singleSubscriber) {
                    singleSubscriber.onSuccess("http://img1.imgtn.bdimg.com/it/u=1225257463,1229468910&fm=21&gp=0.jpg");
                }
            }).map(new Func1<String, Map<Integer, Bitmap>>() {
                @Override
                public Map<Integer, Bitmap> call(String s) {
                    Map<Integer, Bitmap> map = new HashMap<Integer, Bitmap>();
                    map.put(5, getImageBitmap(s));
                    return map;
                }
            }).subscribeOn(Schedulers.io()))
         .doOnSubscribe(new Action0() {
             @Override
             public void call() {
                 pd.show();
             }
         })
            .subscribeOn(AndroidSchedulers.mainThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber<Map<Integer, Bitmap>>() {
                @Override
                public void onCompleted() {
                    if (pd.isShowing()) {
                        pd.dismiss();
                    }
                    Toast.makeText(SiyActivity.this,"5张图片下载完毕",Toast.LENGTH_SHORT).show();
                }

                @Override
                public void onError(Throwable e) {
                    if (pd.isShowing()) {
                        pd.dismiss();
                    }
                }

                @Override
                public void onNext(Map<Integer, Bitmap> integerBitmapMap) {
                    Set<Integer> set = integerBitmapMap.keySet();

                    for (Integer key : set) {
                        switch (key) {
                            case 1:
                                iv1.setImageBitmap(integerBitmapMap.get(1));
                                break;
                            case 2:
                                iv2.setImageBitmap(integerBitmapMap.get(2));
                                break;
                            case 3:
                                iv3.setImageBitmap(integerBitmapMap.get(3));
                                break;
                            case 4:
                                iv4.setImageBitmap(integerBitmapMap.get(4));
                                break;
                            case 5:
                                iv5.setImageBitmap(integerBitmapMap.get(5));
                                break;
                        }

                    }
                }
            });
}

    这种方法使用的是RxJava的Single 类实现的。主要思想和知识与上述方法相同,就不做解释了。


 第一次写博客,水平有限,有不足之处,欢迎指出。


 参考文章:给 Android 开发者的 RxJava 详解

RxJava 入门 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值