Android 基於OkHttp的UI層回調封裝

來源:互聯網
上載者:User

Android 基於OkHttp的UI層回調封裝

用多了OkHttp你會發現,它的返回結果都是在子線程中的,我們對返回結果進行解析後,必須通過handler去更新UI,這麼一來,便會多出很多重複的機械代碼。我們需要進行一層封裝,在onResponse回調方法中對返回結果進行解析,然後將解析結果發出去到UI線程進行更新UI。

因此,我們需要一個解析的方法,我們定義一個介面。

 {    T parse(Response response);} data-snippet-id=ext.cec61e79aa461b746feef11602eb4015 data-snippet-saved=false data-csrftoken=FFB8F3V0-cMZ5HYXGR2ciooUmZ0MydkD49ok data-codota-status=done>public interface Parser {    T parse(Response response);}

該介面傳入okhttp給我們返回的Response ,我們將其進行解析,具體怎麼解析由我們自己實現,比如直接返回字串形式,或者將json轉化為實體類返回等等。

然後我們預設提供幾種實現,首先是直接返回字串。

 {    @Override    public String parse(Response response) {        String result=null;        try {            result=response.body().string();        } catch (IOException e) {            e.printStackTrace();        }        return result;    }} data-snippet-id=ext.516a89f6a521c25637bfc09af9f05630 data-snippet-saved=false data-csrftoken=y3cxcXmx-n-JLN_KclziMMzSOdhEgpZDwWcc data-codota-status=done>public class StringParser implements Parser {    @Override    public String parse(Response response) {        String result=null;        try {            result=response.body().string();        } catch (IOException e) {            e.printStackTrace();        }        return result;    }}

再實現一個將json轉化為實體類的。這個相對複雜一點,需要將實體類的Class對象傳入,因為我們使用的是gson,進行轉換的時候需要該參數。當然這個應該是對所有實體類通用的,很顯然的用到了泛型。

 implements Parser {    private Class mClass=null;    public GsonParser(Class 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;    }} data-snippet-id=ext.eb19a9e01dbbd2b4c51c65e05d4020f0 data-snippet-saved=false data-csrftoken=IZar1yFn-UJkcVXawAxgbtZEYAKOCG964lOA data-codota-status=done>public class GsonParser implements Parser {    private Class mClass=null;    public GsonParser(Class 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;    }}

要在UI層進行更新UI,其實很簡單,解析完成後發生一個訊息就好了,那麼要怎麼做呢。

首先實現Callback介面

 implements com.squareup.okhttp.Callback {    private Parser mParser;    public Callback(Parser 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 {    }} data-snippet-id=ext.7e4050d9ffcd016000b2d5fce948b0e4 data-snippet-saved=false data-csrftoken=3LIOZuhp-3Fb7sxOuPVtPQBo_1fubSAlgGkE data-codota-status=done>public class Callback implements com.squareup.okhttp.Callback {    private Parser mParser;    public Callback(Parser 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 {    }}

通過建構函式將我們的Parser傳遞了進去。

現在假設,我們已經定義好了Handler對象,則在請求失敗的時候我們需要發送一個失敗的訊息

應該有兩個區別訊息的常量

private static final int CALLBACK_SUCCESSFUL=0x01;private static final int CALLBACK_FAILED=0x02;

請求失敗後發送失敗的訊息

public void onFailure(Request request, IOException e) {    Message message=Message.obtain();    message.what=CALLBACK_FAILED;    message.obj=e;    mHandler.sendMessage(message);}

請求成功的回調的處理看個人情況了,這裡認為響應碼是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);    }}

剩下的就是我們的Handler了,我們把它定義成靜態,防止記憶體泄露,由於需要調用外部類的方法,所有還需要持有外部類的引用,同樣的防止記憶體泄露,使用弱引用。同時記得使用主線程的Looper。

 extends Handler{    private WeakReference mWeakReference;    public UIHandler(cn.edu.zafu.coreokhttp.callback.Callback callback){        super(Looper.getMainLooper());        mWeakReference=new WeakReference(callback);    }    @Override    public void handleMessage(Message msg) {    }}private Handler mHandler=new UIHandler(this); data-snippet-id=ext.f51a388bd196ac6782b89d87fe2e01fd data-snippet-saved=false data-csrftoken=WyHTOoMS-rPdG952wjFxjTAikJsxdDhHQ54A data-codota-status=done>static class UIHandler extends Handler{    private WeakReference mWeakReference;    public UIHandler(cn.edu.zafu.coreokhttp.callback.Callback callback){        super(Looper.getMainLooper());        mWeakReference=new WeakReference(callback);    }    @Override    public void handleMessage(Message msg) {    }}private Handler mHandler=new UIHandler(this);

接下來就是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;    }}

從代碼中看到,我們回調了兩個函數,沒錯,這兩個是空函數,由使用者去覆蓋重寫實現

public void onResponse(T t){}public  void onFailure(IOException e){}

這樣有什麼好處呢?

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(parser) {    @Override    public void onResponse(String s) {        Toast.makeText(getApplicationContext(),s,Toast.LENGTH_SHORT).show();    }});

從代碼中看到,我們重寫了我們定義的空函數,直接用Toast顯示出瞭解析結果。

在一定程度上簡化了原來的代碼。但是還不夠精簡,請期待後續的封裝。

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.