Loopj is an Android library for making asynchronous HTTP requests. I like it for its ease of use and simplicity. Created by James Smith, it's also known as "Android Asynchronous HTTP Client", and it's used by companies like Instagram, Pinterest, and many others. It's a good entry point to the world of HTTP libraries, and will help you understand important concepts very easily.
To learn to use this library, we are going to create MovieTrivia, a simple app that connects to a web service to retrieve information about movies or TV shows and displays this information to the user.
1. Setup
To start, create a new Android Studio project, with an empty activity. To include Loopj, copy the dependency from the official website. You can find the dependency under the "Installation and basic usage" section of the website (or just copy the string below).
compile 'com.loopj.android:android-async-http:1.4.9'
The message "Sync Now" will pop up in the upper right-hand corner. Click it so Gradle will download the library and make it available to your project.
Because the app will connect to the internet, we must declare the appropriate permission for the user to authorise. Open your AndroidManifest.xml
file and, just before the application
tag, write:
<uses-permission android:name="android.permission.INTERNET"/>
Now you are ready to start using Loopj in your app.
2. Implementation
We are going to create the simplest possible user interface: just a TextField
to enter a search term, a Button
to do the search, and a TextView
to show the results. Open activity_mail.xml
and add the required UI components as shown below.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="@dimen/activity_vertical_margin" tools:context="com.pdrogfer.movietrivia.MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <EditText android:id="@+id/etSearchTerms" android:layout_width="0dp" android:layout_weight="3" android:layout_height="wrap_content" android:hint="movie or tv show" /> <Button android:id="@+id/btnSearch" android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content" android:text="Search" /> </LinearLayout> <TextView android:id="@+id/tvSearchResults" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="24dp" android:hint="search results"/> </LinearLayout>
Now, as usual, wire up these components in your MainActivity.java
.
public class MainActivity extends AppCompatActivity implements View.OnClickListener { EditText etSearchTerms; Button btnSearch; TextView tvSearchResults; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); etSearchTerms = (EditText) findViewById(R.id.etSearchTerms); btnSearch = (Button) findViewById(R.id.btnSearch); tvSearchResults = (TextView) findViewById(R.id.tvSearchResults); btnSearch.setOnClickListener(this); } @Override public void onClick(View v) { String searchTerm = etSearchTerms.getText().toString(); etSearchTerms.setText(""); // make Loopj HTTP call } }
To keep your code clean and organized, create a separate java class, MyLoopjTask.java
, to contain all the Loopj-specific code and operations. You will need two instance variables, one of type RequestParams
to build the search details into the URL, and another of type AsyncHttpClient
to actually make the HTTP requests. Before going further, check that Android Studio added these necessary imports.
import org.json.JSONObject; import cz.msebera.android.httpclient.Header;
Also create a method that takes the user query as an argument—this is where the actual work will be done.
public class MyLoopjTask { private static final String TAG = "MOVIE_TRIVIA"; AsyncHttpClient asyncHttpClient; RequestParams requestParams; String BASE_URL = "http://www.omdbapi.com/?"; String jsonResponse; public MyLoopjTask() { asyncHttpClient = new AsyncHttpClient(); requestParams = new RequestParams(); } public void executeLoopjCall(String queryTerm) { requestParams.put("s", queryTerm); asyncHttpClient.get(BASE_URL, requestParams, new JsonHttpResponseHandler() { @Override public void onSuccess(int statusCode, Header[] headers, JSONObject response) { super.onSuccess(statusCode, headers, response); jsonResponse = response.toString(); Log.i(TAG, "onSuccess: " + jsonResponse); } @Override public void onFailure(int statusCode, Header[] headers, Throwable throwable, JSONObject errorResponse) { super.onFailure(statusCode, headers, throwable, errorResponse); Log.e(TAG, "onFailure: " + errorResponse); } }); } }
As you see, you can add all the necessary API request parameters keys with the RequestParams
instance (in this case, just the query entered by the user). This version of the get()
method returns a JSON object to onSuccess
, but there are other variations available to fit your needs. (Use Ctrl+O
to see the other versions of this method.)
This is all you need to do to implement a Loopj client to make HTTP calls to a web service. In our case, we want to send our request when the user clicks the "Search" button. So, back in MainActivity
, create an instance of MyLoopjTask
and inside onClick
call executeLoopjCall
with the term entered by the user. MainActivity
will look as follows.
public class MainActivity extends AppCompatActivity implements View.OnClickListener { EditText etSearchTerms; Button btnSearch; TextView tvSearchResults; MyLoopjTask myLoopjTask; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); etSearchTerms = (EditText) findViewById(R.id.etSearchTerms); btnSearch = (Button) findViewById(R.id.btnSearch); tvSearchResults = (TextView) findViewById(R.id.tvSearchResults); btnSearch.setOnClickListener(this); myLoopjTask = new MyLoopjTask(); } @Override public void onClick(View v) { String searchTerm = etSearchTerms.getText().toString(); etSearchTerms.setText(""); // make loopj http call myLoopjTask.executeLoopjCall(searchTerm); } }
Now, if you run the app, you should see the results of your request in the log window.
3. Publish Results to the UI
Separating asynchronous operations into dedicated classes helps keep our code clean, but it means we don't have access to UI elements directly. To show the results of these requests, I recommend creating a listener interface. This is a common strategy, discussed for example in this Stack Overflow question. It has three easy steps.
Create an Interface
First, create an interface with a single method that will be called when the results of the HTTP request are obtained from Loopj.
public interface OnLoopjCompleted { public void taskCompleted(String results); }
Update the Asynchronous Task Handler
In MyLoopjTask
, modify the constructor so it takes a Context
and an OnLoopjCompleted
instance as parameters.
public MyLoopjTask(Context context, OnLoopjCompleted listener) { asyncHttpClient = new AsyncHttpClient(); requestParams = new RequestParams(); this.context = context; this.loopjListener = listener; }
Now, when the request results are available in MyLoopjTask
, pass them to the listener interface's method.
@Override public void onSuccess(int statusCode, Header[] headers, JSONObject response) { super.onSuccess(statusCode, headers, response); jsonResponse = response.toString(); loopjListener.taskCompleted(jsonResponse); Log.i(TAG, "onSuccess: " + jsonResponse); }
Update the Activity
Finally, make the activity you want to update—in this case MainActivity
—implement OnLoopjCompleted
. Update the initialization of myLoopjTask
to myLoopjTask = new MyLoopjTask(this, this);
.
Since your activity now implements OnLoopjCompleted
, Android Studio will force you to implement the method taskCompleted
. There, you can update the UI with the new data.
@Override public void taskCompleted(String results) { tvSearchResults.setText(results); }
4. Conclusion
There you have it. When you run the app, all the data from your asynchronous HTTP request will be displayed to the user. Naturally, you will want to parse the received JSON data to extract just the parts you need. For example, you could display the movie poster by passing the poster image URL to Picasso.
In this tutorial, you've seen how to use Loopj, a library to perform asynchronous HTTP requests in Android. Loopj is easy to use with just a few lines of code. Now you don't have any excuse for not keeping your app up to date with content from your favourite web service!
Comments