There are many great answers already on this question, but a lot of great libraries have come out since those answers were posted. This is intended as a kind of newbie-guide.
I will cover several use cases for performing network operations and a solution or two for each.
REST over HTTP
Typically JSON, but it can be XML or something else.
Full API Access
Let's say you are writing an app that lets users track stock prices, interest rates and currency exchange rates. You find an JSON API that looks something like this:
http://api.example.com/stocks // ResponseWrapper<String> object containing a
// list of strings with ticker symbols
http://api.example.com/stocks/$symbol // Stock object
http://api.example.com/stocks/$symbol/prices // PriceHistory<Stock> object
http://api.example.com/currencies // ResponseWrapper<String> object containing a
// list of currency abbreviation
http://api.example.com/currencies/$currency // Currency object
http://api.example.com/currencies/$id1/values/$id2 // PriceHistory<Currency> object comparing the prices
// of the first currency (id1) to the second (id2)
Retrofit from Square
This is an excellent choice for an API with multiple endpoints and allows you to declare the REST endpoints instead of having to code them individually as with other libraries like Amazon Ion Java or Volley (website: Retrofit).
How do you use it with the finances API?
File build.gradle
Add these lines to your module level build.gradle file:
implementation 'com.squareup.retrofit2:retrofit:2.3.0' // Retrofit library, current as of September 21, 2017
implementation 'com.squareup.retrofit2:converter-gson:2.3.0' // Gson serialization and deserialization support for retrofit, version must match retrofit version
File FinancesApi.java
public interface FinancesApi {
@GET("stocks")
Call<ResponseWrapper<String>> listStocks();
@GET("stocks/{symbol}")
Call<Stock> getStock(@Path("symbol")String tickerSymbol);
@GET("stocks/{symbol}/prices")
Call<PriceHistory<Stock>> getPriceHistory(@Path("symbol")String tickerSymbol);
@GET("currencies")
Call<ResponseWrapper<String>> listCurrencies();
@GET("currencies/{symbol}")
Call<Currency> getCurrency(@Path("symbol")String currencySymbol);
@GET("currencies/{symbol}/values/{compare_symbol}")
Call<PriceHistory<Currency>> getComparativeHistory(@Path("symbol")String currency, @Path("compare_symbol")String currencyToPriceAgainst);
}
Class FinancesApiBuilder
public class FinancesApiBuilder {
public static FinancesApi build(String baseUrl){
return new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(FinancesApi.class);
}
}
Class FinancesFragment snippet
FinancesApi api = FinancesApiBuilder.build("http://api.example.com/"); //trailing '/' required for predictable behavior
api.getStock("INTC").enqueue(new Callback<Stock>(){
@Override
public void onResponse(Call<Stock> stockCall, Response<Stock> stockResponse){
Stock stock = stockCall.body();
// Do something with the stock
}
@Override
public void onResponse(Call<Stock> stockCall, Throwable t){
// Something bad happened
}
}
If your API requires an API key or other header, like a user token, etc. to be sent, Retrofit makes this easy (see this awesome answer to Add Header Parameter in Retrofit for details).
One-off REST API access
Let's say you're building a "mood weather" app that looks up the user's GPS location and checks the current temperature in that area and tells them the mood. This type of app doesn't need to declare API endpoints; it just needs to be able to access one API endpoint.
Ion
This is a great library for this type of access.
Please read msysmilu's great answer to How can I fix 'android.os.NetworkOnMainThreadException'?.
Load images via HTTP
Volley
Volley can also be used for REST APIs, but due to the more complicated setup required, I prefer to use Retrofit from Square as above.
Let's say you are building a social networking app and want to load profile pictures of friends.
File build.gradle
Add this line to your module level build.gradle file:
implementation 'com.android.volley:volley:1.0.0'
File ImageFetch.java
Volley requires more setup than Retrofit. You will need to create a class like this to setup a RequestQueue, an ImageLoader and an ImageCache, but it's not too bad:
public class ImageFetch {
private static ImageLoader imageLoader = null;
private static RequestQueue imageQueue = null;
public static ImageLoader getImageLoader(Context ctx){
if(imageLoader == null){
if(imageQueue == null){
imageQueue = Volley.newRequestQueue(ctx.getApplicationContext());
}
imageLoader = new ImageLoader(imageQueue, new ImageLoader.ImageCache() {
Map<String, Bitmap> cache = new HashMap<String, Bitmap>();
@Override
public Bitmap getBitmap(String url) {
return cache.get(url);
}
@Override
public void putBitmap(String url, Bitmap bitmap) {
cache.put(url, bitmap);
}
});
}
return imageLoader;
}
}
File user_view_dialog.xml
Add the following to your layout XML file to add an image:
<com.android.volley.toolbox.NetworkImageView
android:id="@+id/profile_picture"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
app:srcCompat="@android:drawable/spinner_background"/>
File UserViewDialog.java
Add the following code to the onCreate method (Fragment, Activity) or the constructor (Dialog):
NetworkImageView profilePicture = view.findViewById(R.id.profile_picture);
profilePicture.setImageUrl("http://example.com/users/images/profile.jpg", ImageFetch.getImageLoader(getContext());
Picasso
Picasso is another excellent library from Square. Please see the website for some great examples.