RxJava 多线程控制

来源:互联网 发布:招聘网络主播可信吗 编辑:程序博客网 时间:2024/05/30 04:12

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


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

先贴出代码:

@Overridepublic 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 入门 

0 0