okhttputils返回回调封装

简介

okhttputils 是csdn 鸿洋大神基于okhttp网络请求进行的二次封装

基本请求格式如下

OkHttpUtils
.get()
.url(url)
.addParams("username", "hyman")
.addParams("password", "123")
.build()
.execute(callback);

工具类中提供了 集中callback回调 可以直接获取转换后的数据类型

比如String bitmap

当然也可以自定义,只需要继承工具类中的Callback,然后通过Gson
及自己创建的数据类字节码 进行转化

public abstract class UserCallback extends Callback<User>
{
//非UI线程,支持任何耗时操作
@Override
public User parseNetworkResponse(Response response) throws IOException
{
    String string = response.body().string();
    User user = new Gson().fromJson(string, User.class);
    return user;
}
}

再将该自定义Callback传入请求的execute方法即可

总之这个工具类很方便,具体参开上面的链接

问题

不是说工具类有问题
而是在实际项目中,获取的数据格式各不相同,每一种数据格式就需要新建一个数据bean,对应数据bean还需要创建对应Callback

这就会使得一个业务新建的类太多

遇到一堆业务时,定义的类的数量爆炸

然而数据bean的基本都会有success标志 以及 msg 提示消息
以一个开源网络api为例 Gank的网站提供的api为例 http://gank.io/api/data/Android/10/1

基本格式就是 下面这样一个json
一般都是一个请求标记位 + 数据集合
{“error”:false,
“results”:[{… }]}

并且Callback回调中的 onError 和 onResponse处理很多感觉又可以复用

 .execute(new BitmapCallback()
{
    @Override
    public void onError(Request request, Exception e)
    {
        //根据错误类型决定展示错误界面
    }

    @Override
    public void onResponse(Bitmap bitmap)
    {
        //关闭正在加载界面,展示加载好数据的界面
    }
});

这里做的就是对于对于不同数据bean的处理,以及回掉函数callback的封装,便于应对各种问题
先创建了一个请求结果基类,只包含请求结果,对应gank的json数据

 public class BaseBean {
    /**
     * error : false
     */
    public String error;
}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

然后直接通过GsonFormat插件复制整个gank 的json数据
自动生成获取整个数据的bean ResultData
然后让其继承BaseBean 将其中集合部分 ResultsBean 换成泛型
下面就是修改后的数据bean
只要返回json类型为 error + results类型的只需要新建一个results集合
中的子类数据bean将其传入本来即可,用本类来接收整个数据

public class ResultData<T> extends BaseBean{
    private List<T> results;

    public List<T> getResults() {
        return results;
    }

    public void setResults(List<T> results) {
        this.results = results;
    }
}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

如果数据集合有其他键值的 直接在本类中新加集合即可
比如还有另一个接口返回的时下面的数据
{“error”:”false”,”body”:[…]}
则增加一个新键值,获取数据时注意键值不要选错

public class ResultData<T> extends BaseBean{
    private List<T> results;
    private List<T> body;

    public List<T> getResults() {
        return results;
    }

    public void setResults(List<T> results) {
        this.results = results;
    }

    public List<T> getBody() {
        return body;
    }

    public void setBody(List<T> body) {
        this.body = body;
    }
}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

当然也可以和后端商量,返回数据中集合部分统一用results或者body
就不需要额外添加键值了

有时候,还可能有下面这种数据
{“error”: false , “result”:[…],”count”: 100}
多了一个字段 count
那么就在基类BaseBean中加上这个字段,其他完全不需要变动

public class BaseBean {
    /**
     * error : false
     */
    public String error;

    public int count;
}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

数据bean基本处理完了

下面来实现对于callback封装
先写一个BaseCallback我们可以在这里将部分网络错误处理掉
比如登陆过期,无网络访问,返回404等
还可以在这里关闭加载中界面(我在项目中加载中界面是一个全局的dialog)

public abstract class BaseCallback extends Callback{
    @Override
    public void onError(Call call, Exception e, int id) {
        // TODO: 
    }
}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

查看了OkhttpUtils封装源码,发现网络请求的code 如404等会被放在
异常类的最后,就是onError中的回掉参数e

下面重点来了,数据类型转换,二次封装callback
这里主要进行数据类型转换,这个类直接拿来用就可以了
没什么变动的地方

public abstract class ResponseCallback<T> extends BaseCallback {

    public Type mType;

    public ResponseCallback() {
        mType = getSuperclassTypeParameter(getClass());
    }

    static Type getSuperclassTypeParameter(Class<?> subclass) {
        Type superclass = subclass.getGenericSuperclass();
        if (superclass instanceof Class) {
            throw new RuntimeException("Missing type parameter.");
        }
        ParameterizedType parameterized = (ParameterizedType) superclass;
        return $Gson</span><span class="hljs-variable">$Types.canonicalize(parameterized.getActualTypeArguments()[0]);
    }

    @Override
    public T parseNetworkResponse(Response response, int id) throws Exception {

        return new Gson().fromJson(response.body().string(), mType);
    }
}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

传入泛型,帮你转换

最后我们来尝试一把 看使用情况
直接访问网络,传入ResponseCallback
传入泛型ResultData < ResultBean >

    private void getData() {
        OkHttpUtils
                .get()
                .url("http://gank.io/api/data/Android/3/1")
                .build()
                .execute(new ResponseCallback<ResultData<ResultBean>>(){
                    @Override
                    public void onResponse(ResultData<ResultBean> response, int id) {
                        if (!response.error) {
                           mDataBinding.tv.setText( response.getResults().get(0).get_id());
                        }
                    }
                });
    }
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

获取数据情况,我们的确拿到了数据

这里写图片描述

再换个api试试 http://gank.io/api/history/content/day/2016/05/11

我们来看一些与第一个api获取数据对比
这里写图片描述
图片看的不太清除
这里解释下,大家也可以去通过api访问比对

{“error”:false,”result”:[…]} 一致 但 数组中内容格式完全不同
根据新数据结构创建新数据bean resultbean1

public class ResultBean1 {

    private String _id;
    private String content;
    private String publishedAt;
    private String title;

    public String get_id() {
        return _id;
    }

    public void set_id(String _id) {
        this._id = _id;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public String getPublishedAt() {
        return publishedAt;
    }

    public void setPublishedAt(String publishedAt) {
        this.publishedAt = publishedAt;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

然后再次访问,与上次只有url 和 ResultData中传入的泛型不一致,其他直接复制过来的

    private void getData1() {

        OkHttpUtils
                .get()
                .url("http://gank.io/api/history/content/day/2016/05/11")
                .build()
                .execute(new ResponseCallback<ResultData<ResultBean1>>(){
                    @Override
                    public void onResponse(ResultData<ResultBean1> response, int id) {
                        if (!response.error) {
                            mDataBinding.tv.setText( response.getResults().get(0).get_id());
                        }
                    }
                });

    }
   
   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

再来看一下结果
这里写图片描述

同样时拿到了id

框架搭好后,对于新的后台接口,只需创建一个新的 返回的数据集合中的bean,传入泛型即可
方便好用
看一下结构
这里写图片描述

项目使用的依赖

    compile 'com.zhy:okhttputils:2.6.2'
    compile 'com.google.code.gson:gson:2.8.0'
   
   
  • 1
  • 2

源码下载地址

参考文章

鸿洋okhttputils网络访问框架

okhttp简单封装

(function () {('pre.prettyprint code').each(function () { var lines = (this).text().split(\n).length;var numbering = $('
  • ').addClass('pre-numbering').hide(); (this).addClass(hasnumbering).parent().append( numbering); for (i = 1; i
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在MPI编程中,MPI_Isend()是一个非阻塞的发送函数,该函数在发送消息后立即返回,而不会等待接收方的响应。当我们需要在发送消息的同时执行其他操作时,MPI_Isend()就非常有用了。 下面是使用回调函数封装MPI_Isend()的示例代码: ```c #include <mpi.h> #include <stdio.h> #include <stdlib.h> void isend_callback(MPI_Request *request, MPI_Status *status) { int send_buf; MPI_Get_count(status, MPI_INT, &send_buf); printf("Sent %d\n", send_buf); } int main(int argc, char** argv) { MPI_Init(&argc, &argv); int rank, size; MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); if (size < 2) { printf("Error: program requires at least 2 MPI processes\n"); MPI_Finalize(); return 1; } int send_buf = 42; int recv_buf; MPI_Request request; MPI_Status status; if (rank == 0) { MPI_Isend(&send_buf, 1, MPI_INT, 1, 0, MPI_COMM_WORLD, &request); MPI_Wait(&request, &status); isend_callback(&request, &status); } else { MPI_Recv(&recv_buf, 1, MPI_INT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); printf("Received %d\n", recv_buf); } MPI_Finalize(); return 0; } ``` 在这个示例中,我们使用了一个名为`isend_callback()`的回调函数来处理MPI_Isend()调用的结果。回调函数在MPI_Isend()完成后被异步调用。 在主函数中,我们首先初始化MPI环境,然后获取当前进程的MPI rank和MPI size。如果进程数小于2,我们就退出程序并输出错误信息。 接下来,我们定义了一个发送缓冲区`send_buf`和一个接收缓冲区`recv_buf`。然后,我们调用MPI_Isend()函数来发送数据。在发送完成后,我们调用MPI_Wait()函数来等待MPI_Isend()的完成。最后,我们调用isend_callback()回调函数来处理发送操作的结果。 对于接收方,我们只需要调用MPI_Recv()函数来接收数据即可。在接收完成之后,我们输出接收缓冲区中的数据。 最后,我们调用MPI_Finalize()函数来结束MPI环境并退出程序。 这就是如何使用回调函数封装MPI_Isend()的方法。通过使用回调函数,我们可以实现更加灵活和高效的MPI编程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值