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

满堂花醉三千客,一剑霜寒十四州。这篇文章主要讲述RX系列四 | RxAndroid | 加载图片 | 提交表单相关的知识,希望能为你提供帮助。
RX系列四 | Rxandroid | 加载图片 | 提交表单 说实话, 学Rxjava就是为了我们在Android中运用的更加顺手一点, 也就是RxAndroid, 我们还是先一步步来, 学会怎么去用的比较好, 之前的三篇算是铺垫, 让你有一点认识, 那Rx在Android中有什么好处呢? 我们先模拟一些原始功能和他对比下
一.加载图片 【RX系列四 | RxAndroid | 加载图片 | 提交表单】很多人说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加载的处理方式, 这种方式将对我们产生很大的影响, 我们最起码现在懂得了他的一点套路了, 我们来看下运行结果
RX系列四 | RxAndroid | 加载图片 | 提交表单

文章图片

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

    推荐阅读