Android OkHttp-based UI Layer callback Encapsulation

Source: Internet
Author: User

Android OkHttp-based UI Layer callback Encapsulation

When OkHttp is used, you will find that all the returned results are in the subthread. After parsing the returned results, you must update the UI through handler, there will be a lot of repeated mechanical code. We need to encapsulate the returned results in the onResponse callback method, and then send the parsing results to the UI thread to update the UI.

Therefore, we need a resolution method, and we define an interface.

 {    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);}
  

This interface is used to pass in the Response returned by okhttp, And we will parse it. We will implement the specific parsing by ourselves, for example, directly returning the string form, or converting json into returning the object class.

Then we provide several implementations by default. The first is to directly return a string.

 {    @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;    }}
  

Then, convert json into Entity classes. This is relatively complicated. We need to pass in Class objects of the object Class, because we use gson, which is required for conversion. Of course, this should be common to all entity classes, and it is clear that generic is used.

 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; }}
        
       
      
     
   
  
 

Updating the UI on the UI Layer is actually very simple. After Parsing is complete, a message is ready. How can this problem be solved.

First, implement the Callback Interface

 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 { }}
      
     
    
  
 

The constructor passes our Parser in.

Now, if we have defined the Handler object, we need to send a failed message when the request fails.

There should be two constants that distinguish messages

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

Message that fails to be sent after request failure

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

The processing of callback for successful requests depends on my personal situation. Here, the response code starting with 2 is regarded as request success, otherwise it is considered as failure, for example, 400,500. If the request succeeds, the Parser's parse method is called for parsing.

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);    }}

The rest is our Handler. We define it as static to prevent memory leakage. Because we need to call external class methods, all of them need to hold external class references, it also prevents Memory leakage and uses weak references. Remember to use the Logoff of the main thread.

 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);
    
   
 

The next step is to process the handleMessage method.

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;    }}

We can see from the code that we have called back two functions. Yes, these two are empty functions, which are overwritten by the user.

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

What are the benefits?

Parser can be used repeatedly to avoid multiple resolutions and use the same code to avoid writing Handler to process UI Layer updates.

Now let's take a look at how to use it.

We simply use StringParser to parse the returned results

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();    }});
  

From the code, we can see that we have rewritten the empty function we defined and directly used Toast to display the parsing result.

The original code is simplified to a certain extent. But it is not concise enough. Please look forward to future encapsulation.

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

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.