RX系列四 | RxAndroid | 加载图片 | 提交表单

RX系列四 | RxAndroid | 加载图片 | 提交表单



说实话,学RxJava就是为了我们在Android中运用的更加顺手一点,也就是RxAndroid,我们还是先一步步来,学会怎么去用的比较好,之前的三篇算是铺垫,让你有一点认识,那Rx在Android中有什么好处呢?我们先模拟一些原始功能和他对比下

一.加载图片

很多人说Rx出来之后,是编程思想的一种进阶,实际上我学习了这种思想之后,确实是觉得有了很大的改变,不过,需要一点学习成本再加上,需要对原先的思想有些改观,使得我依旧有点不适应,不知道为啥,可能就像用了好几年的Eclipse,突然让我用Android Studio的时候的那种感觉,不过,技术在进步,每个人也需要去接受,没有好坏之分,那我们就在讲解Rx之前,我们先把思路,逻辑来做一个铺垫吧,首先,我们要准备一些东西的,因为涉及了网络请求,下载等功能,所以我们肯定是要去添加下网络权限

 <!--网络权限-->
 <uses-permission android:name="android.permission.INTERNET"/>

然后我们再来说一下,我们现在要干的事情,先易后难,我们先来加载一张图片,我们传统的做法是通过AsyncTask去做,但是这样的代码很长很沉闷,而在我们的Activity中,其实上一个Activity的本身他是有很多的工作要做的,这样导致代码会很多,不容易重构等,所以才会有现在的MVC,MVP等架构去解耦,所以我们既然Rx编程本身是一套很简洁的代码,那我们应该用什么方法去合理的实现呢?我们来写个解析的方法,因为需要用到OkHttp,所以请在gradle里添加

  //OkHttp3
  compile 'com.squareup.okhttp3:okhttp:3.+'

这样才好去加载,我们写个方法吧

   //加载图片
    private Observable<byte[]> lodingImg(String imgPath){
        return Observable.create(new Observable.OnSubscribe<byte[]>() {
            @Override
            public void call(Subscriber<? super byte[]> subscriber) {
                if(!subscriber.isUnsubscribed()){
                    //解析图片
                    OkHttpClient client = new OkHttpClient();
                    Request request = new Request.Builder().url(imgPath).build();
                    client.newCall(request).enqueue(new Callback() {
                        @Override
                        public void onFailure(Call call, IOException e) {
                            subscriber.onError(e);
                        }

                        @Override
                        public void onResponse(Call call, Response response) throws IOException {
                            if(response.isSuccessful()){
                                byte [] bytes = response.body().bytes();
                                if(bytes != null){
                                    subscriber.onNext(bytes);
                                }
                            }
                            //结束
                            subscriber.onCompleted();
                        }
                    });
                }
            }
        });
    }

这个方法可以看到我们返回值是一个byte字节数组参数的被观察者Observable,然后传递一个地址,我们就直接return回去一个Observable,在Observable里面,我们做了什么事情呢?其实我们就直接用OkHttp去解析了一张图片,拿到了byte之后,通过subscriber.onNext(bytes)传递给了观察者,让他去做操作,当然,别忘了调用onCompleted去告知观察者已经结束了操作,而在观察者这边,你需要做什么呢?

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_download:
                lodingImg(IMG_PATH)
                        //网络访问
                        .observeOn(Schedulers.io())
                        //UI线程
                        .observeOn(AndroidSchedulers.mainThread())
                        //订阅
                        .subscribe(new Observer<byte[]>() {
                    @Override
                    public void onCompleted() {
                        Log.i(TAG,"onCompleted");
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.i(TAG,e.toString());
                    }

                    @Override
                    public void onNext(byte[] bytes) {
                        Bitmap bitmap = BitmapFactory.decodeByteArray(bytes,0,bytes.length);
                        img.setImageBitmap(bitmap);
                    }
                });
                break;
        }
    }

其实可以看到,我们直接就去订阅了一个subscribe,在onNext里面,通过BitmapFactory的方法转换成一个Bitmap,这就是Rx加载的处理方式,这种方式将对我们产生很大的影响,我们最起码现在懂得了他的一点套路了,我们来看下运行结果

OK,也是很顺利的加载出来了

二.提交表单

如果说加载图片是get的话,那提交表单就是post了,我们来看一下提交表单该怎么写,我们假设是做一个登陆注册的功能,那就很简单了,我们看下我们这次要做的代码

   //登录
    private Observable<String> fromLogin(String url, Map<String,String> params){
        return Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                if(!subscriber.isUnsubscribed()){
                    OkHttpClient client = new OkHttpClient();
                    FormBody.Builder builder = new FormBody.Builder();
                    if(params!=null && !params.isEmpty()){
                        for (Map.Entry<String, String>entry:params.entrySet()){
                            builder.add(entry.getKey(),entry.getValue());
                        }
                    }
                    RequestBody requestBody = builder.build();
                    //构建post请求
                    Request request = new Request.Builder().url(url).post(requestBody).build();
                    client.newCall(request).enqueue(new Callback() {
                        @Override
                        public void onFailure(Call call, IOException e) {
                            subscriber.onError(e);
                        }

                        @Override
                        public void onResponse(Call call, Response response) throws IOException {
                            if(response.isSuccessful()){
                                subscriber.onNext(response.body().string());
                            }
                            //访问结束
                            subscriber.onCompleted();
                        }
                    });
                }
            }
        });
    }

这段代码里面,我们可用看到,我们定义了一个方法,返回值是一个String类型的被观察者Observable,而传递的参数就是登陆的地址和一个Map键值对,我们直接return一个Observable即可,在里面我们使用OkHTTP提交表单,最后通过onNext返回结果,通过onCompleted告知结束操作,而在我们的观察者里面我们应该怎么做?

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_login:
                String name = et_name.getText().toString().trim();
                String password = et_password.getText().toString().trim();
                if (!TextUtils.isEmpty(name)) {
                    if(!TextUtils.isEmpty(password)){
                        Map<String,String> params = new HashMap<>();
                        params.put("name",name);
                        params.put("password",password);
                        fromLogin(LOGIN_URL,params)
                                //网络访问
                                .observeOn(Schedulers.io())
                                //UI线程
                                .observeOn(AndroidSchedulers.mainThread())
                                .subscribe(new Observer<String>() {
                                    @Override
                                    public void onCompleted() {
                                        Log.i(TAG,"onCompleted");
                                    }

                                    @Override
                                    public void onError(Throwable e) {
                                        Log.i(TAG,e.toString());
                                    }

                                    @Override
                                    public void onNext(String s) {
                                        Log.i(TAG,s);
                                    }
                                });
                    }else {
                        Toast.makeText(this, "密码不能为空", Toast.LENGTH_SHORT).show();
                    }
                }else {
                    Toast.makeText(this, "账号不能为空", Toast.LENGTH_SHORT).show();
                }
                break;
        }
    }

在这个点击事件里,我们可用看到直接把参数塞进去后通过subscribe订阅拿到结果,这样如果登录成功就跳转了,这就是一整套的逻辑,这里没有地址,就不演示了,到这里,我相信大家对基本的使用应该是没什么问题了,一句话概括,就是异步,让我们的代码逻辑性更强,当然, 现在的例子还不能友好的表达出精髓,大家有兴趣的可以接着后续的系列

Sample下载:系列最后一篇提供

有兴趣的可以加群:555974449

时间: 2024-10-26 08:38:38

RX系列四 | RxAndroid | 加载图片 | 提交表单的相关文章

让广告代码不再影响你的网页加载速度_表单特效

做一些联盟广告时,由于联盟广告的加载慢,整体页面的显示速度也会变慢,如果加入下面的代码就可以有效地解决这个问题. 第一步:把这段代码放在你要放广告的网页位置: <span id=\"andy\">广告载入中...</span> 第二步:把这段代码放到页底: <span id=\"span_andy\">  这里放广告的JS代码或其他加载速度比较慢的内容都可以.  </span>  <script type=\&q

RoR + ExtJS 如何实现表单数据加载和提交?

问题描述 使用RoR + ExtJS.ExtJS生成一个FormPanel,一个文本框和提交按钮,文本框数据自动从RoR的controller加载,提交表单到controller的一个action.请问如何实现?另外,是否用到了json?RoR如何返回json给ExtJS? 问题补充:lizhi92574 写道 解决方案 var form= new Ext.form.FormPanel({reader : new Ext.data.JsonReader({}) //只定数据解析器 对应表单元素n

Glide加载图片流程(Part One)

由于项目的需要,这几天对Glide的执行过程做了简单的了解,希望对想了解Glide基本用法的朋友能有所帮助. 注意 此系列博客基于Glide V3.7.0版本源码 这里假设朋友们能够在Android Studio中正确引入Glide相关的依赖,如果有不懂的朋友,请参考官方文档引入依赖. 为了让朋友们尽快的了解Glide加载图片的流程,我们就从最简单的方式入手.请看如下代码: ImageView fullscreenView = (ImageView) findViewById(R.id.full

Android中使用二级缓存、异步加载批量加载图片完整案例

一.问题描述 Android应用中经常涉及从网络中加载大量图片,为提升加载速度和效率,减少网络流量都会采用二级缓存和异步加载机制,所谓二级缓存就是通过先从内存中获取.再从文件中获取,最后才会访问网络.内存缓存(一级)本质上是Map集合以key-value对的方式存储图片的url和Bitmap信息,由于内存缓存会造成堆内存泄露, 管理相对复杂一些,可采用第三方组件,对于有经验的可自己编写组件,而文件缓存比较简单通常自己封装一下即可.下面就通过案例看如何实现网络图片加载的优化. 二.案例介绍 案例新

jQuery滚动加载图片实现原理_jquery

本文主要通过以下几方面来说明懒加载技术的原理,个人前端小菜,有错误请多多指出 一.什么是图片滚动加载? 通俗的讲就是:当访问一个页面的时候,先把img元素或是其他元素的背景图片路径替换成一张大小为1*1px图片的路径(这样就只需请求一次),只有当图片出现在浏览器的可视区域内时,才设置图片正真的路径,让图片显示出来.这就是图片懒加载. 二.为什要使用这个技术? 比如一个页面中有很多图片,如淘宝.京东首页等等,如果一上来就发送这么多请求,页面加载就会很漫长,如果js文件都放在了文档的底部,恰巧页面的

xutils-Listview加载图片错位

问题描述 Listview加载图片错位 我用得是Xutils 然后有的item有图片有的不显示,结果错位了 下面代码: //图片url public View getView(final int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub final ViewHolder holder; if (convertView == null) { holder = new View

opencv加载图片的问题,有时候加载是白色的图片

问题描述 opencv加载图片的问题,有时候加载是白色的图片 opencv加载图片的问题,有时候加载是白色的图片,不知道是什么原因? 解决方案 参考这个看看:http://blog.csdn.net/wangyaninglm/article/details/38958915 解决方案二: 参考下这篇文章:http://blog.csdn.net/miehuo/article/details/17734867 解决方案三: 好的,我回头看看这个博客 解决方案四: 纯白色的吗?和原来图像不符合?看下

在WIN8系统加载图片可打印出图片,但在XP系统只能显示图片并不能打印出图片?

问题描述 在WIN8系统加载图片可打印出图片,但在XP系统只能显示图片并不能打印出图片? 如题,在WIN8系统MFC单文档应用程序中加载图片可以显示并打印出图片,但在XP系统中运行程序只能显示图片并不能打印出图片这是什么情况?是系统兼容性的问题吗?求大神解答 解决方案 检查下你的xp是不是山寨盗版,精简了打印的组件或者缺少驱动程序,也可能是你安装了虚拟打印机之类的软件. 解决方案二: 在XP系统上的文字部分都能打印出来,但就是图片打印不出来,应该不是打印机驱动的问题吧 解决方案三: 加载图片程序

bitmap-ViewPager加载图片内存溢出怎么解决?

问题描述 ViewPager加载图片内存溢出怎么解决? @Override public Object instantiateItem(View view int position) { View mv = mListViews.get(position); ((ViewPager) view).addView(mv 0); // 加载图片 ImageView iv = (ImageView) mv.findViewById(R.id.imageView); try {//图片的名称 Strin