編輯:關於Android編程
用多了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 ParsermParser; 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.Callbackcallback){ 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顯示出了解析結果。
在一定程度上簡化了原來的代碼。但是還不夠精簡,請期待後續的封裝。
Android沒有自帶顏色編輯器,為了讓用戶直觀的選擇顏色,做了這麼一個控件,效果圖如下:上方顏色條為主顏色條,用戶可以選擇大致需要的顏色,下方是該顏色的平衡調節,可以調
一、首先來看看效果這是一個帶有刪除按鈕的輸入文本框, 需要新建一個類繼承自EditText, 先把代碼貼出來, 然後在解釋:示例代碼如下:public class Edi
本文實例講述了Android AnalogClock簡單使用方法。分享給大家供大家參考,具體如下:AnalogClock組件的使用很簡單,先來看看效果圖:AnalogCl
一、數據綁定框架DataBinding介紹:Android的新框架DataBinding給我們帶來了很大的方便,以前可能需要在每個Activity裡寫很多的findVie