OkHttp's Ins and Outs (Part 1)

OkHttp's Ins and Outs (Part 1)

This is the first part of OkHttp tutorial.

1. A bit about history

At the beginning, Android had their HTTP client APIs for sending and requesting data over the network (HttpUrlConnection and HttpClient by Apache). Even though they both could do pretty much all possible necessary job, they required lots of boilerplate code that is usually implemented inside AsyncTask or background thread methods. Besides, both had limitations in regard to request cancellation and connection pooling.

2. Advantages

OkHttp client provides the implementation of HttpUrlConnection and Apache Client interfaces by working on the top of java socket without any extra dependencies. Moreover, it brings many different advanced features such as connection pooling, transparent gzip compression, resource caching to avoid the network for repeated requests. It has also ability to recover from common connection problems, if the service has several IP addresses it can retry alternatives on connection failure. It supports synchronous and asynchronous calls. OkHttp supports Android 2.3 or higher, and minimum JDK requirement is 1.7.

Synchronous - the call usually requires AsyncTask wrapper around it, so it does not allow the cancellation of request. AsyncTask does usually leak the activity context, that's why this method is not preferable most of the time.

Asynchronous - the calling this way is preferable since it allows native cancellation, such as tagging multiple requests, and cancelling them all with a single method call. Usually cancel method is invoked inside onPause() or onDestroy() lifecycle methods of the activity.

This is a brief introduction for OkHttp client APIs, however, I would personally recommending going over HttpUrlConnection and Apache Client APIs just once, to see the difference and advantages of OkHttp. In the following sections, we will see several basic and advanced examples for OkHttp client APIs.

3. Set -up

If you are using Maven as a build tool, you can add the library for dependencies in the pom.xml in the following way.

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>3.4.2</version>
</dependency>

You can check for the latest version here in the link Maven Central

For gradle build, you can add the following into build.gradle in your app folder. And add internet permission in manifest file

implementation 'com.squareup.okhttp3:okhttp:3.4.1'

<uses-permission android:name="android.permission.INTERNET"/>

4. Connection and simple activity example

Here below we will see one simple activity doing http request using OkHttp library, as you can see it is a synchronous call and wrapped around with AsyncTask.

public class MainActivity extends AppCompatActivity {


    private String url = "https://reqres.in/api/users/2";
    private TextView loadedText;
    @Overrideprotected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        loadedText = findViewById(R.id.loadedtext);

        OkHttpHandler okHttpHandler = new OkHttpHandler();
        okHttpHandler.execute(url);

    }

    class OkHttpHandler extends AsyncTask<String, String, String>{
        OkHttpClient okHttpClient = new OkHttpClient();

        @Override 
protected String doInBackground(String... strings) {
            Request.Builder builder = new Request.Builder();
            builder.url(strings[0]);
            Request request = builder.build();

            try {
                Response response = okHttpClient.newCall(request).execute();
                return response.body().string();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Overrideprotected void onPostExecute(String s) {
            super.onPostExecute(s);
            loadedText.setText(s);
        }
    }

}

The following examples will flow pretty much in the same structure, synchronous calls wrapped around with background threads, however I will implement each example inside a method only.

5. GET Request Examples

5.1 Synchronous GET

To make a synchronous get request, we need to build the instance of Request object, and pass the url and call it from the client. Once the client execute method is done, it returns the instance of Response object, as shown below.

public String getSynchronous(String url) throws IOException {
    Request.Builder builder = new Request.Builder();
    builder.url(url);
    Request request = builder.build();
    Response response = okHttpClient.newCall(request).execute();
    return response.body().string();
}

5.2 Asynchronous GET

To make an asynchronous call, we need to simply enqueue the call, and we can read the response only when it is readable and its response headers are ready.

public void getAsynchronous(String url){
    Request.Builder builder = new Request.Builder();
    builder.url(url);
    Request request = builder.build();
    Call call  = okHttpClient.newCall(request);
    call.enqueue(new Callback() {
        @Overridepublic void onFailure(Call call, IOException e) {
            //failed();
        }

        @Overridepublic void onResponse(Call call, Response response) throws IOException {
            //Handle the response;
        }
    });

}

We can also add the query parameters while sending get request, we will see the example in the next section.

5.3 GET Request with Parameters

To send the parameterized request, HttpUrl.Builder can help us to make up the url, and then we can use the parameterized url to build our request object as in the example below.

public String parameterizedGet(String baseUrl) throws IOException {
    
    //Adding the parameters for url
    HttpUrl.Builder urlBuilder = HttpUrl.parse(url).newBuilder();
    urlBuilder.addQueryParameter("user","1");
    String url = urlBuilder.build().toString();
    
    
    Request request = new Request.Builder()
            .url(url)
            .build();
    Call call = okHttpClient.newCall(request);
    Response response = call.execute();
    return response.body().string();
}

6. POST Request Examples

6.1 Basic post request

To send the post request, we initially need to form RequestBody to send it with post request.

public String postRequest(String url, String username, String password) throws IOException {
    //request body
    RequestBody requestBody = new FormBody.Builder()
            .add("username",username).add("password",password).build();

    Request request = new Request.Builder()
            .url(url)
            .post(requestBody)
            .build();
    Call call = okHttpClient.newCall(request);
    return call.execute().body().string();

}

Next example, we will see how to send the post request with Authorization.

6.2 Post request with Authorization

In this example, we send the post request with a basic authentication example, and will see how to send the string as a body of the request.

public Response basicAuthentication() throws IOException {
    String postBody = "post body";
    Request request = new Request.Builder()
            .url(url)
            .addHeader("Authorization",
                    Credentials.basic("test","test"))
            .post(RequestBody.create(MediaType.parse("text/x-markdown; charset=utf-8"),postBody))
            .build();
    Call call = okHttpClient.newCall(request);
    Response response = call.execute();
    return response;
}

Next we will see how to send the request with JSON as a request body

6.3 Post with JSON

Here, to send the JSON body, we just need to change request body expected type parameter as in the example

public Response requestPostJson(String url) throws IOException {
    String jsonBody = "{\"id\":1,\"name\":\"John\"}";

    RequestBody requestBody = RequestBody.
            create(MediaType.parse("application/json; charset=utf-8"), jsonBody);
    Request request = new Request.Builder().url(url).post(requestBody).build();
    return okHttpClient.newCall(request).execute();
}

6.4 Multipart Post Request

To send the multipart request, we need to build our request body as a multi-part body to post our files as shown in the example below

public void sendMultiPartPost(String url) throws IOException {
   // building the multipart request bodu
    RequestBody requestBody = new MultipartBody.Builder()
            .setType(MultipartBody.FORM)
            .addFormDataPart("username", "test")
            .addFormDataPart("password", "test")
            .addFormDataPart("file", "file.txt",
                    RequestBody.create(MediaType.parse("application/octet-stream"),
                            new File("src/test/resources/test.txt")))
            .build();

    Request request = new Request.Builder()
            .url(url)
            .post(requestBody)
            .build();

    Call call = okHttpClient.newCall(request);
    Response response = call.execute();
}

This is the first part of the tutorial. In next section, I will be posting about how to upload media, work with timeouts, custom headers and cancelling calls.

To read the second part of the tutorial, please click the link here.

Thanks for reading and learning!




Zohidjon Akbarov

Senior Android Developer | Toptal Member

6y

Super useful, thank you sharing. 

Sherali Obidov

Sr. Software Engineer at Google

6y

Nice article and super useful !  It would be easy to focus on okhttp related code if you can clean/remove some code and leave a comment there.    super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); loadedText = findViewById(R.id.loadedtext); can be replaced with // assign view here  :) 

Like
Reply

To view or add a comment, sign in

More articles by Farruh Habibullaev

  • Good API architecture principles

    Claimer: This article is purely written from my own experience in software development and design, however in some…

  • Practical Dijkstra's Algorithm

    In computer science and discrete mathematics, we have encountered the concept of "single - source shortest path" many…

  • Android Core: Looper, Handler, and HandlerThread

    I have posted this article for those who don't have any idea how multi-threading architecture in android works, and…

  • OkHttp's Ins and Outs (Part 2)

    This is the second part of OkHttp tutorial. You can find the first part of tutorial in the link here.

    1 Comment
  • Creational Design Patterns

    Creational design patterns are one of three categories of design patterns (creational, structural, and behavioral…

  • Decorator and Proxy Pattern

    Decorator pattern Decorator pattern is one of the structural design patterns and used to modify the functionality of…

  • S.O.L.I.D Principles in OO programming

    SOLID is the first five essential principles of object oriented programming for building a well designed, working…

  • Mediator and Command Pattern

    Mediator Pattern Mediator pattern falls into category of behavioral patterns since it deals with behavior of the…

  • Composite Design Pattern

    Composite design patterns falls into one of structural design patterns. Before diving into the composite design…

    2 Comments
  • Iterator Design Pattern

    Iterator design pattern falls into the category of behavioral pattern. Iterator pattern is used to provide iteration…

Insights from the community

Explore topics