首页 > 移动开发 > Android 基于OkHttp的UI层回调封装

Android 基于OkHttp的UI层回调封装

用多了OkHttp你会发现,它的返回结果都是在子线程中的,我们对返回结果进行解析后,必须通过handler去更新UI,这么一来,便会多出很多重复的机械代码。我们需要进行一层封装,在onResponse回调方法中对返回结果进行解析,然后将解析结果发出去到UI线程进行更新UI。

因此,我们需要一个解析的方法,我们定义一个接口。

public interface Parser<T> {
    T parse(Response response);
}
  • 1
  • 2
  • 3
  • 4

该接口传入okhttp给我们返回的Response ,我们将其进行解析,具体怎么解析由我们自己实现,比如直接返回字符串形式,或者将json转化为实体类返回等等。

然后我们默认提供几种实现,首先是直接返回字符串。

public class StringParser implements Parser<String> {
    @Override
    public String parse(Response response) {
        String result=null;
        try {
            result=response.body().string();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

再实现一个将json转化为实体类的。这个相对复杂一点,需要将实体类的Class对象传入,因为我们使用的是gson,进行转换的时候需要该参数。当然这个应该是对所有实体类通用的,很显然的用到了泛型。

public class GsonParser<T> implements Parser<T> {
    private Class<T> mClass=null;
    public GsonParser(Class<T> clazz){
        if (clazz==null){
            throw new IllegalArgumentException("Class can't be null");
        }
        this.mClass=clazz;
    }
    @Override
    public T parse(Response response) {
        try {
            Gson gson=new Gson();
            String str=response.body().string();
            T t=gson.fromJson(str,mClass);
            return t;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

要在UI层进行更新UI,其实很简单,解析完成后发生一个消息就好了,那么要怎么做呢。

首先实现Callback接口

public class Callback<T> implements com.squareup.okhttp.Callback {
    private Parser<T> mParser;

    public Callback(Parser<T> mParser) {
        if (mParser == null) {
            throw new IllegalArgumentException("Parser can't be null");
        }
        this.mParser = mParser;
    }

    @Override
    public void onFailure(Request request, IOException e) {

    }

    @Override
    public void onResponse(Response response) throws IOException {

    }


}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

通过构造函数将我们的Parser传递了进去。

现在假设,我们已经定义好了Handler对象,则在请求失败的时候我们需要发送一个失败的消息

应该有两个区别消息的常量

private static final int CALLBACK_SUCCESSFUL=0x01;
private static final int CALLBACK_FAILED=0x02;
  • 1
  • 2

请求失败后发送失败的消息

public void onFailure(Request request, IOException e) {
    Message message=Message.obtain();
    message.what=CALLBACK_FAILED;
    message.obj=e;
    mHandler.sendMessage(message);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

请求成功的回调的处理看个人情况了,这里认为响应码是2开头的就是请求成功,否则也认为是失败,比如400,500。如果请求成功了就调用Parser的parse方法解析

public void onResponse(Response response) throws IOException {
    if (response.isSuccessful()) {
        T parseResult = mParser.parse(response);
        Message message=Message.obtain();
        message.what=CALLBACK_SUCCESSFUL;
        message.obj=parseResult;
        mHandler.sendMessage(message);
    } else {
        Message message=Message.obtain();
        message.what=CALLBACK_FAILED;
        mHandler.sendMessage(message);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

剩下的就是我们的Handler了,我们把它定义成静态的,防止内存泄露,由于需要调用外部类的方法,所有还需要持有外部类的引用,同样的防止内存泄露,使用弱引用。同时记得使用主线程的Looper。

static class UIHandler<T> extends Handler{
    private WeakReference mWeakReference;
    public UIHandler(cn.edu.zafu.coreokhttp.callback.Callback<T> callback){
        super(Looper.getMainLooper());
        mWeakReference=new WeakReference(callback);
    }

    @Override
    public void handleMessage(Message msg) {

    }
}
private Handler mHandler=new UIHandler(this);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

接下来就是handleMessage方法的处理了。

public void handleMessage(Message msg) {
    switch (msg.what){
        case CALLBACK_SUCCESSFUL: {
            T t = (T) msg.obj;
            cn.edu.zafu.coreokhttp.callback.Callback callback = (cn.edu.zafu.coreokhttp.callback.Callback) mWeakReference.get();
            if (callback != null) {
                callback.onResponse(t);
            }
            break;
        }
        case CALLBACK_FAILED: {
            IOException e = (IOException) msg.obj;
            cn.edu.zafu.coreokhttp.callback.Callback callback = (cn.edu.zafu.coreokhttp.callback.Callback) mWeakReference.get();
            if (callback != null) {
                callback.onFailure(e);
            }
            break;
        }
        default:
            super.handleMessage(msg);
            break;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

从代码中看到,我们回调了两个函数,没错,这两个是空函数,由用户去覆盖重写实现

public void onResponse(T t){

}
public  void onFailure(IOException e){

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

这样有什么好处呢?

  • Parser可以重复使用,避免多次解析使用同样的代码
  • 避免编写多次Handler去处理UI层更新

现在我们看看如何使用。

我们简单的使用StringParser进行解析返回结果

OkHttpClient okHttpClient=new OkHttpClient();
StringParser parser=new StringParser();
Request request = new Request.Builder().url("https://www.baidu.com").build();
okHttpClient.newCall(request).enqueue(new cn.edu.zafu.coreokhttp.callback.Callback<String>(parser) {
    @Override
    public void onResponse(String s) {
        Toast.makeText(getApplicationContext(),s,Toast.LENGTH_SHORT).show();
    }

});
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

从代码中看到,我们重写了我们定义的空函数,直接用Toast显示出了解析结果。

在一定程度上简化了原来的代码。但是还不够精简,请期待后续的封装。

源码下载 
http://download.csdn.net/detail/sbsujjbcy/9163435


本文固定链接: http://www.devba.com/index.php/archives/6393.html | 开发吧

报歉!评论已关闭.