[Android] Simple OkHttp encapsulation-Auxiliary framework
Preface
There is no doubt that OkHttp is powerful. OkHttp can accomplish everything at the network layer and is applicable to any situation; this is because OkHttp has to write a lot of code to complete the corresponding configuration every time it constructs a request. Here we will share a helper framework that encapsulates OkHttp to minimize your development burden. If you don't want to talk about it, you can see it later.
Native
Here is an example of how okhttp is used in several native scenarios.
GET
Public void get () {Request. Builder builder = new Request. Builder (). url ("http://www.xx.com? Id = dd & aa = sdd "). get (); Request request = builder. build (); Call call = new OkHttpClient (). newCall (request); // synchronize try {call.exe cute ();} catch (IOException e) {e. printStackTrace ();} // asynchronous call. enqueue (new Callback () {@ Override public void onFailure (Request request, IOException e) {}@ Override public void onResponse (Response response) throws IOException {}});}
Form
public void form() { FormEncodingBuilder formEncodingBuilder = new FormEncodingBuilder(); // Add values formEncodingBuilder.add("id", "dd"); formEncodingBuilder.add("name", "sdd"); RequestBody body = formEncodingBuilder.build(); Request request = new Request.Builder().post(body).build(); // do call... }
File
public void file() { MultipartBuilder builder = new MultipartBuilder(); builder.type(MultipartBuilder.FORM); builder.addFormDataPart("id", "dd"); builder.addFormDataPart("name", "sdd"); RequestBody fileBody = RequestBody.create(MediaType.parse("image/png"), new File("aa.png")); builder.addFormDataPart("head", "aa.png", fileBody); RequestBody body = builder.build(); Request request = new Request.Builder().post(body).build(); // do call... }
I have to say that okhttp is a very Nice encapsulated framework. Even if the file is sent, it is okay to just a few lines of code.
But what if we need to perform UI switching when returning or parse the returned data in JSON format?
It is easy to get the data and then switch to a thread, and then use GSON to parse it.
But can we simplify it? Because each request requires building build-request-send-resolution, these operations are rare, but there is no need to repeat them.
Original Intention
The reason for re-encapsulation is to stop the build process from appearing. Of course, the function cannot be limited to this.
What if you get an ID after logging on and require that the ID be included in subsequent operations?
Is it added to each request parameter? This is an encapsulation.
Encapsulation is only for simplicity ~
Function UI thread switching optional Callback (any UI thread or sub-thread selected) parameter normalization, the GET and POST methods are the same as passing parameters. For callback of upload/download progress, you can simply set the Head part and automatically add the required parameter String/JSON/byte/File at each request... Can be used in the same simple way
Because of the large number of auxiliary code, it is different here. Here we only demonstrate how to use it.
Asynchronous GET
Http.getAsync("http://wthrcdn.etouch.cn/weather_mini", new UiCallback
() { @Override public void onFailure(Request request, Response response, Exception e) { log("getAsync:onFailed"); } @Override public void onSuccess(String response, int code) { log("getAsync:onSuccess:" + response); } }, new StrParam("citykey", 101010100));
Because it is a get request, the citykey in this parameter will be automatically parsed to the url.
http://wthrcdn.etouch.cn/weather_mini?citykey=101010100
Synchronize GET
final String url = "http://wthrcdn.etouch.cn/weather_mini?citykey=101010100";String str = Http.getSync(String.class, url);log("getSync1:" + str);str = Http.getSync(url, new ThreadCallback
() { @Override public void onFailure(Request request, Response response, Exception e) { log("getSync2:onFailed"); } @Override public void onSuccess(String response, int code) { log("getSync2:onSuccess:" + response); }});log("getSync2:" + str);
The synchronous mode supports two cases: Callback and No.
Of course, even if Callback is added, the method will not continue until the execution is complete. The reason for this is to facilitate the direct processing of the ui in callback.
It is worth noting that the return type needs to be specified. If there is no Callback, You need to input the class of the return type.
Of course, if you pass in callback, which of the following class is called callback?
Account account = Http.getSync(Account.class, url);User user = Http.getSync(User.class, url);String str = Http.getSync(String.class, url, new StrParam("citykey", 101010100));
Callback is also shown in the preceding figure.
The difference between asynchronous and synchronous is the method name:
Http. getSync () Http. getAsync () Http. postSync () Http. postAsync () Http. uploadSync () Http. uploadAsync () Http. downloadSync () Http. downloadAsync ()
By default, upload and download have the callProgress callback progress function.
POST
String value1 = "xxx"; String value2 = "xxx"; String url = "http://www.baidu.com"; Http.postAsync(url, new HttpCallback
() { @Override public void onFailure(Request request, Response response, Exception e) { e.printStackTrace(); } @Override public void onSuccess(String response, int code) { log(response); } }, new StrParam("value1", value1), new StrParam("value2", value2));
THE post request method is basically the same as the get method.
Upload
File file = getAssetsFile();Http.uploadAsync("http://img.hoop8.com/upload.php", "uploadimg", file, new UiCallback
() { @Override public void onProgress(long current, long count) { super.onProgress(current, count); log("uploadAsync onProgress:" + current + "/" + count); mUpload.setProgress((int) ((current * 100.00 / count))); } @Override public void onFailure(Request request, Response response, Exception e) { e.printStackTrace(); log("uploadAsync onFailed"); } @Override public void onSuccess(String response, int code) { log("uploadAsync onSuccess:" + response); }});
The upload part is also very simple. If you need parameters, which is the same as the Post method. Of course, the input parameter is not StrParam but IOParam.
During upload, you can only pass the name of the file + file; or IOParam; or StrParam + IOParam; of course, the ultimate point is that you can pass the Param type.
The Param type is a combination of StrParam and IOParam.
You can also upload files like this:
Http.uploadAsync("url", callback, new IOParam("uploadimg", file));Http.uploadAsync("url", callback, new StrParam[]{new StrParam("id", 123456), new StrParam("name", "qiujuer")}, new IOParam("uploadimg", file));Http.uploadAsync("url", callback, new Param("id", 123456), new Param("name", "qiujuer"), new Param("uploadimg", file));
Download
Http.downloadAsync("https://raw.githubusercontent.com/qiujuer/OkHttpPacker/master/release/sample.apk", getSDPath(), null, null, new UiCallback
() {@Overridepublic void onProgress(long current, long count) { super.onProgress(current, count); log("downloadAsync onProgress:" + current + "/" + count); mDownload.setProgress((int) ((current * 100.00 / count)));}@Overridepublic void onFailure(Request request, Response response, Exception e) { e.printStackTrace(); log("downloadAsync onFailed");}@Overridepublic void onSuccess(File response, int code) { log("downloadAsync onSuccess:" + response.getAbsolutePath());}});
To facilitate the download, the File is forcibly returned. When you get the File, it is the downloaded File.
Download is only asynchronous, and parameters can also be input.
In terms of input parameters, you can pass only one storage directory. The file name is specified based on the url.
Of course, you can also pass the directory + file name.
Or you can directly input a File ).
The Object is used to set the Tag when it is passed in, so that OKHTTP can cancel.
Parameters
The most supported parameters are Post in all methods, so Post is used for demonstration here.
// Http. postAsync ("url", callback); // StrParamHttp. postAsync ("url", callback, new StrParam ("id", 113321); // ListList
StrParamList = new ArrayList <> (); strParamList. add (new StrParam ("id", 113321); Http. postAsync ("url", callback, strParamList); // MapMap
StrParamMap = new HashMap <> (); strParamMap. put ("id", "113321"); Http. postAsync ("url", callback, strParamMap); // StringHttp. postAsync ("url", callback, "This is post body. "); // ByteHttp. postAsync ("url", callback, new byte [] {1, 2}); // FileHttp. postAsync ("url", callback, new File ("img.png"); // JSONJSONObject jsonObject = new JSONObject ("json data"); Http. postAsync ("url", callback, jsonObject); // JSONArrayJSONArray jsonArray = new JSONArray (); Http. postAsync ("url", callback, jsonArray );
Request Construction
In this framework, all requests will build the url and parameters through the request builder. Therefore, it is very easy to include specific parameters for each request.
Method 1:
RequestBuilder builder = Http. getInstance (). getRequestBuilder (); (RequestCallBuilder) builder ). setBuilderListener (new RequestCallBuilder. builderListener () {// construct the Request header. Here you can initialize some Request headers @ Override public void onCreateBuilder (Request. builder builder) {builder. addHeader ("User-Agent", "User-Agent"); builder. addHeader ("Head-Content", "Head-Content");} // call @ Override public boolean onBuildGetPara when building Get MS (StringBuilder sb, boolean isFirst) {// isFirst is used to tell if it is the first parameter // because the first parameter of the GET request is added "? ", And the following parameter is added with" & "// It is used to tell whether the current parameter already exists. // If so, false is returned, returns true if no parameter is added. // you may need to change the name to haveParam. if (isFirst) {isFirst = false; sb. append ("? ");} Else {sb. append ("&");} sb. append ("uid ="); sb. append ("qiujuer"); return isFirst;} // call @ Override public void onBuildFormBody (FormEncodingBuilder formEncodingBuilder) {formEncodingBuilder when building the Form body. add ("uid", "qiujuer");} // call @ Override public void onBuildMultipartBody (MultipartBuilder multipartBuilder) {multipartBuilder when constructing a Multipart body. addFormDataPart ("uid", "qiujuer ");}});
Second
import com.squareup.okhttp.FormEncodingBuilder;import com.squareup.okhttp.MultipartBuilder;import com.squareup.okhttp.Request;import net.qiujuer.common.okhttp.impl.RequestCallBuilder;/** * Created by qiujuer * on 16/1/13. */public class MyRequestBuilder extends RequestCallBuilder { @Override protected boolean buildGetParams(StringBuilder sb, boolean isFirst) { if (isFirst) { isFirst = false; sb.append("?"); } else { sb.append("&"); } sb.append("uid="); sb.append("qiujuer"); return isFirst && super.buildGetParams(sb, isFirst); } @Override protected FormEncodingBuilder buildFormBody(FormEncodingBuilder formEncodingBuilder) { formEncodingBuilder.add("uid", "qiujuer"); return super.buildFormBody(formEncodingBuilder); } @Override protected MultipartBuilder buildMultipartBody(MultipartBuilder multipartBuilder) { multipartBuilder.addFormDataPart("uid", "qiujuer"); return super.buildMultipartBody(multipartBuilder); } @Override protected Request.Builder createBuilder() { Request.Builder builder = super.createBuilder(); builder.addHeader("User-Agent", "User-Agent"); builder.addHeader("Head-Content", "Head-Content"); return builder; }}
Http.getInstance().setRequestBuilder(new MyRequestBuilder());
Both methods are OK, but the first method is recommended, which is convenient and quick. In the future, we can encapsulate it again in the first method. It is easy to encapsulate it into the Param layer.
Parser
In this framework, all the returned data will be parsed by the parser; This achieves the purpose of directly parsing the JSON data as a Class.
By default, GSON is used for parsing. You can also rewrite the parser.
GSON Configuration
Sometimes the returned data style is not the default Gson style (usually the time string), which will cause parsing failure. Here is a simple method.
GsonBuilder gsonBuilder = new GsonBuilder();gsonBuilder.setDateFormat("yyyy-MM-dd HH:mm:ss");Gson gson = gsonBuilder.create();Http.getInstance().setResolver(new GsonResolver(gson));
FastJson
If you do not want to use Gson for parsing, you may adopt FastJson. You can rewrite the parser.
import net.qiujuer.common.okhttp.core.Resolver;import java.lang.reflect.Type;/** * Created by qiujuer * on 16/1/13. */public class MyResolver implements Resolver { @Override public Object analysis(String rsp, Type type) { return null; } @Override public Object analysis(String rsp, Class subclass) { return null; }}
There are two resolution methods, both of which need to be improved by yourself.
Rsp is the string returned by the network.
Type is to wait for the returned ClassType
Cookie
With regard to Cookie support, Cookie storage is disabled by default. If you want to store the website Cookie to a local file and use the current Cookie each time you access the file.
// Allow CookieHttp. enableSaveCookie (getApplication () to be stored; // clear CookieHttp. removeCookie (); // obtain all CookieHttp. getCookie ();
OkHttpClient
Sometimes you need to obtain the current Client. For example, you can set the Client to a Glide network drive.
OkHttpClient client = Http.getClient();// GlideGlide.get(application).register(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory(client));
Debugging
If you need to know the Url and parameter information of each request, you can turn on the LOG switch.
Http.DEBUG = true;
About HTTPS
In the current framework, HTTPS support is not directly integrated. Instead, a CertTool certificate tool is used for HTTPS support.
With CertTool, you can easily set a local certificate file for HTTPS requests.
CertTool.setCertificates(Http.getClient(),new FileInputStream(new File()));
CallbackHttpCallback
This Callback is required by default, where:
In the onStart UI thread, the onFinish UI thread executes onProgress, onFailure, and onSuccess subthreads to execute ThreadCallback.
All Callbacks are executed in subthreads.
UICallback
All Callbacks are executed in the UI thread.