Bs part

Just a few boring things on the job, want to gossip can see, do not want to use directly to see the subject of a paragraph. I changed a job two months ago, and I went to a company where I was the only one developing, and started from scratch. I went there even though there was nothing, because I personally thought it was a good opportunity. I used to work for two years copying or maintaining other people’s codes. MVC project is neither fish nor fowl, network request, caching, project structure now looks worse mess (now think so, because these two months feel they have a lot of improved), but at that time I was so comfortable choose stay there, very fortunate to have come out, or else face so fierce competition, I think I might be out of the market. May now have a lot of people in a more comfortable company with a good salary has been no move ideas, I just give you a suggestion, if you like technology, like challenges, suggested earlier from these companies, each company as their springboard to the growth of technology, but it is not recommended in less than a year in work, too much is not good, At the very least, the company has to learn all the technology to leave, otherwise it is difficult to learn things in the end. All right, cut the crap. Let’s get started on today’s topic.

Retrofit??

Now Retrofit is probably familiar to a lot of people, after all, there are a lot of articles in the developer community about Retrofit+RxJava+MVP, and it was a little confusing when I first read about it, but after a little bit of research and using it in a project, I found that it’s not that hard to do, so let me give you some advice. Don’t come up to see some open source project source code, so you will be confused, you can try to understand the application scenario, try in the project or write something to practice, and then look at the source code. Retrofit, in layman’s terms, is a framework for HTTP requests, with an Interface to define the IMPLEMENTATION of the API, and comments to set up some requests.

public interface GitHubService 
{
    @GET("users/{user}/repos") 
    Call> listRepos(@Path("user") String user);
}Copy the code

Just like the code above, all network request interfaces are defined in an Interface and then implemented using the Create () method in Retrofit, Detail can see [Retrofit website] (square. Making. IO/Retrofit / [] Retrofit API (square. Making. IO/Retrofit / 2…. I won’t say much about Retrofit here, because this article is mainly about OkHttp in use, so if you want to learn about Retrofit, check out other sources

OkHttp is used in Retrofit

OkHttp. OkHttp is a request client based on Http. Retrofit and OkHttp are both open source projects of Square. Let’s talk about the configuration of OKHTTP when I use it in the project. First of all, okHTTP is really great. When you use it in your project, the log input is very detailed. Things like Content-Type, headers, parameter return values are all displayed in great detail. We can provide interface by implementing [Interceptor] (square. Making. IO/okhttp / 3. X /… Here’s an example: When COMMUNICATING with our background staff, I found that each interface has two common parameters version and device. It is impossible for us to add these two parameters to each interface when defining it. For convenience, we will add them uniformly in one place. We can provide a custom Interceptor for this:

public class CommonParamsInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); // HttpUrl HttpUrl = request.url().newBuilder().addQueryParameter("version", ConstantConfig.APP_VERSION_CODE) .addQueryParameter("token", ConstantConfig.APP_TOKEN) .addQueryParameter("device", "Android").build(); request = request.newBuilder().url(httpUrl).build(); return chain.proceed(request); }}Copy the code

This can be achieved on each request add the above parameters, but some things are always hurt some than you might think, because the backend interface is developed by two people, one person told me that all the request method is get and post all support, it also didn’t find any problem at that time, the background and another man found no debugging, If you specify that a post request must be used, this method will not work. If you specify that a POST request must be used, this method will not work. Alas… No way, can only go to modify, and then is a search, finally solved, the code is as follows:

public class CommonParamsInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); Formbody.builder newBody = new formBody.builder (); newBody.add("version", ConstantConfig.APP_VERSION_CODE) .add("token", ConstantConfig.APP_TOKEN).add("device", "Android").build(); FormBody oldBody = (FormBody) request.body(); FormBody oldBody = (FormBody) request.body(); for (int i = 0; i < oldBody.size(); i++) { newBody.add(oldBody.encodedName(i), oldBody.encodedValue(i)); } request = request.newBuilder().post(newBody.build()).build(); chain.proceed(request); }}Copy the code

This allows you to submit form data and set common parameters for GET and POST. This example shows that with OKHTTP we can intercept at every step, setting up caches, headers, and so on. A custom Interceptor can be set when initializing okHTTP, for example:

/** * OkHttp initialization, set the cache directory, set the maximum request time, */ public void initOkHttp() {okHttpClient.builder Builder = new okHttpClient.builder (); CustomParamsInterceptor paramsInterceptor = new CustomParamsInterceptor(); builder.addInterceptor(paramsInterceptor); if (BuildConfig.DEBUG) { HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(); loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY); builder.addInterceptor(loggingInterceptor); } / / http://www.jianshu.com/p/93153b34310e cache File cacheFile = new File (ConstantConfig CACHE_DIR, "/ NetCache"); Cache cache = new Cache(cacheFile, 1024 * 1024 * 50); Interceptor cacheInterceptor = new Interceptor() { @Override public Response intercept(Chain chain) throws IOException {  Request request = chain.request(); if (! Util.isNetworkConnected(App.getmAppContext())) { request = request.newBuilder().cacheControl(CacheControl.FORCE_CACHE).build(); } Response response = chain.proceed(request); if (Util.isNetworkConnected(App.getmAppContext())) { int maxAge = 0; Response.newbuilder ().header(" cache-control ", "public, max-age=" + maxAge).build(); response.newBuilder() (" cache-control ", "public, max-age=" + maxAge).build(); } else {// If there is no network, set timeout to 4 weeks int maxStale = 60 * 60 * 24 * 28; response.newBuilder().header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale) .build(); } return response; }}; builder.cache(cache).addInterceptor(cacheInterceptor); // Set timeout builder.connectTimeout(15, timeunit.seconds); builder.readTimeout(20, TimeUnit.SECONDS); builder.writeTimeout(20, TimeUnit.SECONDS); / / error reconnection builder. RetryOnConnectionFailure (true); okHttpClient = builder.build(); }Copy the code

Okhttp is so convenient and flexible that we can play around with it. However, the most annoying thing was that the interface on ios required me to pass the parameters in JSON format.

Here we would like to say that data transmission format and data format are two different things. We generally think that data format makes the data returned by our mobile phone in the receiving interface API is a JSON String, but there are several formats for transmitting data with background interface:

  • Application/XHTML + XML: XHTML format
  • Application/XML: XML data format
  • Application/Atom + XML: Atom XML aggregation format
  • Application /json: Json data format
  • Application/PDF: in PDF format
  • Application/MSWORD: Word document format
  • Application /octet-stream: binary stream data (e.g. common file downloads)
  • Application/X-www-form-urlencoded: default encType, form form data is coded as key/value format and sent to the server (form default submit data format)

    The data transfer format for HTTP requests without setting the default is the last Application/X-www-form-urlencoded, and this setting is a key value passed as a parameter, But our background requires me to use application/ JSON format to pass the data, alas… Then the above two methods are not feasible, there is no way, and then, finally also worked out, the code is as follows:

public class CustomParamsInterceptor implements Interceptor { private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8"); @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); ArrayMap paramsMap = new ArrayMap(); ParamsMap. Put (" version ", "1.0"); paramsMap.put("token", ""); paramsMap.put("device", "Android"); if (request.body() instanceof FormBody) { FormBody oldBody = (FormBody) request.body(); for (int i = 0; i < oldBody.size(); i++) { paramsMap.put(oldBody.encodedName(i), oldBody.encodedValue(i)); } } Gson gson = new Gson(); Applog. I ("Gson parameter format --" + gson.toJson(paramsMap)); RequestBody body = RequestBody.create(JSON, gson.toJson(paramsMap)); request = request.newBuilder().post(body).build(); return chain.proceed(request); }}Copy the code

This is all my experience today, I will write an article every day about the problems encountered in the development and the technical points learned, if you are interested in can pay attention to, although it is still a small white, but the efforts will not be in vain, come on SAO nian. My project uses MVP+RxJava+Retrofit and a lot of things are still being improved. If you are interested, please discuss with me. Thank you for reading.