Top Related Projects
Square’s meticulous HTTP client for the JVM, Android, and GraalVM.
A type-safe HTTP client for Android and the JVM
An image loading and caching library for Android focused on smooth scrolling
An Android library for managing images and the memory they use.
An asynchronous, callback-based Http client for Android built on top of Apache's HttpClient libraries.
Quick Overview
Ion is an Android library that simplifies asynchronous processing, particularly for networking, image loading, and caching. It provides a fluent, easy-to-use API for making HTTP requests, handling JSON, and loading images efficiently, making it a powerful tool for Android developers.
Pros
- Simplified asynchronous programming with a clean, chainable API
- Efficient image loading and caching capabilities
- Seamless integration with Android's UI thread
- Supports various data types and formats (JSON, Bitmap, File, etc.)
Cons
- May introduce additional overhead for simple applications
- Learning curve for developers new to reactive programming concepts
- Limited customization options for advanced use cases
- Dependency on external libraries (e.g., AndroidAsync)
Code Examples
Loading an image into an ImageView:
Ion.with(imageView)
.placeholder(R.drawable.placeholder_image)
.error(R.drawable.error_image)
.load("https://example.com/image.jpg");
Performing a GET request and parsing JSON:
Ion.with(context)
.load("https://api.example.com/data")
.asJsonObject()
.setCallback(new FutureCallback<JsonObject>() {
@Override
public void onCompleted(Exception e, JsonObject result) {
// Handle the result or error
}
});
Uploading a file:
Ion.with(context)
.load("POST", "https://api.example.com/upload")
.setMultipartFile("file", new File("/path/to/file"))
.asString()
.setCallback(new FutureCallback<String>() {
@Override
public void onCompleted(Exception e, String result) {
// Handle the response or error
}
});
Getting Started
- Add the Ion dependency to your app's
build.gradle
file:
dependencies {
implementation 'com.koushikdutta.ion:ion:3.1.0'
}
- Initialize Ion in your application class:
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
Ion.getDefault(this).configure().setLogging("MyApp", Log.DEBUG);
}
}
- Use Ion in your activities or fragments:
Ion.with(this)
.load("https://api.example.com/data")
.asJsonObject()
.setCallback((e, result) -> {
if (e != null) {
// Handle error
} else {
// Process the JSON result
}
});
Competitor Comparisons
Square’s meticulous HTTP client for the JVM, Android, and GraalVM.
Pros of OkHttp
- More actively maintained with frequent updates and improvements
- Supports HTTP/2 and SPDY protocols for faster network performance
- Extensive documentation and widespread adoption in the Android community
Cons of OkHttp
- Steeper learning curve for beginners compared to Ion's simpler API
- Requires more boilerplate code for basic operations
- Lacks built-in image loading and caching features
Code Comparison
Ion:
Ion.with(context)
.load("http://example.com/api")
.asJsonObject()
.setCallback(new FutureCallback<JsonObject>() {
@Override
public void onCompleted(Exception e, JsonObject result) {
// Handle response
}
});
OkHttp:
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://example.com/api")
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onResponse(Call call, Response response) throws IOException {
// Handle response
}
@Override
public void onFailure(Call call, IOException e) {
// Handle failure
}
});
A type-safe HTTP client for Android and the JVM
Pros of Retrofit
- Type-safe HTTP client with annotation-based API definition
- Seamless integration with OkHttp for efficient networking
- Supports synchronous and asynchronous requests
Cons of Retrofit
- Steeper learning curve due to annotation-based approach
- Requires more boilerplate code for complex requests
- Limited built-in image loading capabilities
Code Comparison
Retrofit:
public interface GitHubService {
@GET("users/{user}/repos")
Call<List<Repo>> listRepos(@Path("user") String user);
}
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
GitHubService service = retrofit.create(GitHubService.class);
Ion:
Ion.with(context)
.load("https://api.github.com/users/koush/repos")
.asJsonArray()
.setCallback(new FutureCallback<JsonArray>() {
@Override
public void onCompleted(Exception e, JsonArray result) {
// handle result
}
});
Retrofit offers a more structured approach with interface-based API definitions, while Ion provides a simpler, fluent API for quick implementation. Retrofit excels in type safety and integration with other Square libraries, whereas Ion offers easier image loading and caching out of the box.
Pros of Volley
- Official Google library, ensuring long-term support and integration with Android ecosystem
- Built-in request prioritization and cancellation
- Efficient memory usage through automatic scheduling of network requests
Cons of Volley
- Limited file upload and download capabilities compared to Ion
- Lacks some advanced features like cookie management and easy request chaining
- Slightly more verbose API for simple requests
Code Comparison
Ion:
Ion.with(context)
.load("http://example.com/api")
.asJsonObject()
.setCallback(new FutureCallback<JsonObject>() {
@Override
public void onCompleted(Exception e, JsonObject result) {
// Handle result
}
});
Volley:
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest
(Request.Method.GET, "http://example.com/api", null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
// Handle response
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
// Handle error
}
});
requestQueue.add(jsonObjectRequest);
Both libraries offer efficient networking solutions for Android, with Ion providing a more streamlined API for common tasks and additional features, while Volley offers tighter integration with the Android ecosystem and better request management.
An image loading and caching library for Android focused on smooth scrolling
Pros of Glide
- More active development and maintenance
- Better memory management and caching system
- Wider range of supported image formats and transformations
Cons of Glide
- Steeper learning curve for beginners
- Larger library size compared to Ion
Code Comparison
Ion:
Ion.with(imageView)
.placeholder(R.drawable.placeholder)
.error(R.drawable.error)
.load("http://example.com/image.jpg");
Glide:
Glide.with(context)
.load("http://example.com/image.jpg")
.placeholder(R.drawable.placeholder)
.error(R.drawable.error)
.into(imageView);
Both Ion and Glide are popular image loading libraries for Android, but they have some key differences. Glide offers more advanced features and better performance, especially for memory management and caching. It also supports a wider range of image formats and transformations.
However, Glide's extensive feature set can make it more complex for beginners to use compared to Ion. Additionally, Glide's library size is larger than Ion's, which may be a consideration for apps with strict size constraints.
In terms of code, both libraries have similar syntax for basic image loading operations. The main difference is in the order of method chaining and the use of with()
to start the request.
An Android library for managing images and the memory they use.
Pros of Fresco
- More advanced memory management and caching system
- Better support for progressive JPEG loading
- Extensive customization options for image processing and display
Cons of Fresco
- Larger library size, which may impact app size
- Steeper learning curve due to more complex API
- Limited support for older Android versions compared to Ion
Code Comparison
Ion:
Ion.with(imageView)
.placeholder(R.drawable.placeholder)
.error(R.drawable.error)
.load("http://example.com/image.jpg");
Fresco:
Uri uri = Uri.parse("http://example.com/image.jpg");
ImageRequest request = ImageRequestBuilder.newBuilderWithSource(uri)
.setProgressiveRenderingEnabled(true)
.build();
DraweeController controller = Fresco.newDraweeControllerBuilder()
.setImageRequest(request)
.setOldController(draweeView.getController())
.build();
draweeView.setController(controller);
Summary
Fresco offers more advanced features and better performance for complex image loading scenarios, particularly for apps with heavy image usage. However, it comes at the cost of increased complexity and library size. Ion, on the other hand, provides a simpler API and smaller footprint, making it suitable for projects with basic image loading needs or those prioritizing ease of use and minimal impact on app size.
An asynchronous, callback-based Http client for Android built on top of Apache's HttpClient libraries.
Pros of android-async-http
- Simpler API with fewer dependencies, making it easier to integrate and use
- Better support for handling cookies and persistent connections
- More extensive documentation and community support
Cons of android-async-http
- Less feature-rich compared to ion, especially for image loading and caching
- Limited support for modern Android features like Kotlin coroutines
- Slower development and fewer updates in recent years
Code Comparison
android-async-http:
AsyncHttpClient client = new AsyncHttpClient();
client.get("https://api.example.com/data", new JsonHttpResponseHandler() {
@Override
public void onSuccess(int statusCode, Headers headers, JSON response) {
// Handle successful response
}
});
ion:
Ion.with(context)
.load("https://api.example.com/data")
.asJsonObject()
.setCallback(new FutureCallback<JsonObject>() {
@Override
public void onCompleted(Exception e, JsonObject result) {
// Handle response or error
}
});
Both libraries offer asynchronous HTTP requests, but ion provides a more fluent API and built-in JSON parsing. android-async-http requires separate handling for different response types, while ion offers a more unified approach to various data formats and operations like image loading.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
Android Asynchronous Networking and Image Loading
Download
Features
- Kotlin coroutine/suspend support
- Asynchronously download:
- Easy to use Fluent API designed for Android
- Automatically cancels operations when the calling Activity finishes
- Manages invocation back onto the UI thread
- All operations return a Future and can be cancelled
- HTTP POST/PUT:
- text/plain
- application/json - both JsonObject and POJO
- application/x-www-form-urlencoded
- multipart/form-data
- Transparent usage of HTTP features and optimizations:
- SPDY and HTTP/2
- Caching
- Gzip/Deflate Compression
- Connection pooling/reuse via HTTP Connection: keep-alive
- Uses the best/stablest connection from a server if it has multiple IP addresses
- Cookies
- View received headers
- Grouping and cancellation of requests
- Download progress callbacks
- Supports file:/, http(s):/, and content:/ URIs
- Request level logging and profiling
- Support for proxy servers like Charles Proxy to do request analysis
- Based on NIO and AndroidAsync
- Ability to use self signed SSL certificates
Samples
The included documented ion-sample project includes some samples that demo common Android network operations:
- Twitter Client Sample
- Download JSON from a server (twitter feed)
- Populate a ListView Adapter and fetch more data as you scroll to the end
- Put images from a URLs into ImageViews (twitter profile pictures)
- File Download with Progress Bar Sample
- Get JSON and show images with the Image Search Sample
More Examples
Looking for more? Check out the examples below that demonstrate some other common scenarios. You can also take a look at 30+ ion unit tests in the ion-test.
Get JSON
Ion.with(context)
.load("http://example.com/thing.json")
.asJsonObject()
.setCallback(new FutureCallback<JsonObject>() {
@Override
public void onCompleted(Exception e, JsonObject result) {
// do stuff with the result or error
}
});
Post JSON and read JSON
JsonObject json = new JsonObject();
json.addProperty("foo", "bar");
Ion.with(context)
.load("http://example.com/post")
.setJsonObjectBody(json)
.asJsonObject()
.setCallback(new FutureCallback<JsonObject>() {
@Override
public void onCompleted(Exception e, JsonObject result) {
// do stuff with the result or error
}
});
Post application/x-www-form-urlencoded and read a String
Ion.with(getContext())
.load("https://koush.clockworkmod.com/test/echo")
.setBodyParameter("goop", "noop")
.setBodyParameter("foo", "bar")
.asString()
.setCallback(...)
Post multipart/form-data and read JSON with an upload progress bar
Ion.with(getContext())
.load("https://koush.clockworkmod.com/test/echo")
.uploadProgressBar(uploadProgressBar)
.setMultipartParameter("goop", "noop")
.setMultipartFile("archive", "application/zip", new File("/sdcard/filename.zip"))
.asJsonObject()
.setCallback(...)
Download a File with a progress bar
Ion.with(context)
.load("http://example.com/really-big-file.zip")
// have a ProgressBar get updated automatically with the percent
.progressBar(progressBar)
// and a ProgressDialog
.progressDialog(progressDialog)
// can also use a custom callback
.progress(new ProgressCallback() {@Override
public void onProgress(long downloaded, long total) {
System.out.println("" + downloaded + " / " + total);
}
})
.write(new File("/sdcard/really-big-file.zip"))
.setCallback(new FutureCallback<File>() {
@Override
public void onCompleted(Exception e, File file) {
// download done...
// do stuff with the File or error
}
});
Setting Headers
Ion.with(context)
.load("http://example.com/test.txt")
// set the header
.setHeader("foo", "bar")
.asString()
.setCallback(...)
Load an image into an ImageView
// This is the "long" way to do build an ImageView request... it allows you to set headers, etc.
Ion.with(context)
.load("http://example.com/image.png")
.withBitmap()
.placeholder(R.drawable.placeholder_image)
.error(R.drawable.error_image)
.animateLoad(spinAnimation)
.animateIn(fadeInAnimation)
.intoImageView(imageView);
// but for brevity, use the ImageView specific builder...
Ion.with(imageView)
.placeholder(R.drawable.placeholder_image)
.error(R.drawable.error_image)
.animateLoad(spinAnimation)
.animateIn(fadeInAnimation)
.load("http://example.com/image.png");
The Ion Image load API has the following features:
- Disk and memory caching
- Bitmaps are held via weak references so memory is managed very efficiently
- ListView Adapter recycling support
- Bitmap transformations via the .transform(Transform)
- Animate loading and loaded ImageView states
- DeepZoom for extremely large images
Futures
All operations return a custom Future that allows you to specify a callback that runs on completion.
public interface Future<T> extends Cancellable, java.util.concurrent.Future<T> {
/**
* Set a callback to be invoked when this Future completes.
* @param callback
* @return
*/
public Future<T> setCallback(FutureCallback<T> callback);
}
Future<String> string = Ion.with(context)
.load("http://example.com/string.txt")
.asString();
Future<JsonObject> json = Ion.with(context)
.load("http://example.com/json.json")
.asJsonObject();
Future<File> file = Ion.with(context)
.load("http://example.com/file.zip")
.write(new File("/sdcard/file.zip"));
Future<Bitmap> bitmap = Ion.with(context)
.load("http://example.com/image.png")
.intoImageView(imageView);
Cancelling Requests
Futures can be cancelled by calling .cancel():
bitmap.cancel();
json.cancel();
Blocking on Requests
Though you should try to use callbacks for handling requests whenever possible, blocking on requests is possible too.
All Futures have a Future
JsonObject json = Ion.with(context)
.load("http://example.com/thing.json").asJsonObject().get();
Seamlessly use your own Java classes with Gson
public static class Tweet {
public String id;
public String text;
public String photo;
}
public void getTweets() throws Exception {
Ion.with(context)
.load("http://example.com/api/tweets")
.as(new TypeToken<List<Tweet>>(){})
.setCallback(new FutureCallback<List<Tweet>>() {
@Override
public void onCompleted(Exception e, List<Tweet> tweets) {
// chirp chirp
}
});
}
Logging
Wondering why your app is slow? Ion lets you do both global and request level logging.
To enable it globally:
Ion.getDefault(getContext()).configure().setLogging("MyLogs", Log.DEBUG);
Or to enable it on just a single request:
Ion.with(context)
.load("http://example.com/thing.json")
.setLogging("MyLogs", Log.DEBUG)
.asJsonObject();
Log entries will look like this:
D/MyLogs(23153): (0 ms) http://example.com/thing.json: Executing request.
D/MyLogs(23153): (106 ms) http://example.com/thing.json: Connecting socket
D/MyLogs(23153): (2985 ms) http://example.com/thing.json: Response is not cacheable
D/MyLogs(23153): (3003 ms) http://example.com/thing.json: Connection successful
Request Groups
By default, Ion automatically places all requests into a group with all the other requests created by that Activity or Service. Using the cancelAll(Activity) call, all requests still pending can be easily cancelled:
Future<JsonObject> json1 = Ion.with(activity, "http://example.com/test.json").asJsonObject();
Future<JsonObject> json2 = Ion.with(activity, "http://example.com/test2.json").asJsonObject();
// later... in activity.onStop
@Override
protected void onStop() {
Ion.getDefault(activity).cancelAll(activity);
super.onStop();
}
Ion also lets you tag your requests into groups to allow for easy cancellation of requests in that group later:
Object jsonGroup = new Object();
Object imageGroup = new Object();
Future<JsonObject> json1 = Ion.with(activity)
.load("http://example.com/test.json")
// tag in a custom group
.group(jsonGroup)
.asJsonObject();
Future<JsonObject> json2 = Ion.with(activity)
.load("http://example.com/test2.json")
// use the same custom group as the other json request
.group(jsonGroup)
.asJsonObject();
Future<Bitmap> image1 = Ion.with(activity)
.load("http://example.com/test.png")
// for this image request, use a different group for images
.group(imageGroup)
.intoImageView(imageView1);
Future<Bitmap> image2 = Ion.with(activity)
.load("http://example.com/test2.png")
// same imageGroup as before
.group(imageGroup)
.intoImageView(imageView2);
// later... to cancel only image downloads:
Ion.getDefault(activity).cancelAll(imageGroup);
Proxy Servers (like Charles Proxy)
Proxy server settings can be enabled all Ion requests, or on a per request basis:
// proxy all requests
Ion.getDefault(context).configure().proxy("mycomputer", 8888);
// or... to proxy specific requests
Ion.with(context)
.load("http://example.com/proxied.html")
.proxy("mycomputer", 8888)
.getString();
Using Charles Proxy on your desktop computer in conjunction with request proxying will prove invaluable for debugging!
Viewing Received Headers
Ion operations return a ResponseFuture, which grant access to response properties via the Response object. The Response object contains the headers, as well as the result:
Ion.with(getContext())
.load("http://example.com/test.txt")
.asString()
.withResponse()
.setCallback(new FutureCallback<Response<String>>() {
@Override
public void onCompleted(Exception e, Response<String> result) {
// print the response code, ie, 200
System.out.println(result.getHeaders().code());
// print the String that was downloaded
System.out.println(result.getResult());
}
});
Get Ion
Maven
<dependency>
<groupId>com.koushikdutta.ion</groupId>
<artifactId>ion</artifactId>
<version>(insert latest version)</version>
</dependency>
Gradle
dependencies {
compile 'com.koushikdutta.ion:ion:(insert latest version)'
}
Local Checkout (with AndroidAsync dependency)
git clone git://github.com/koush/AndroidAsync.git
git clone git://github.com/koush/ion.git
cd ion/ion
ant -Dsdk.dir=$ANDROID_HOME release install
Jars are at
- ion/ion/bin/classes.jar
- AndroidAsync/AndroidAsync/bin/classes.jar
Hack in Eclipse
git clone git://github.com/koush/AndroidAsync.git
git clone git://github.com/koush/ion.git
- Import the project from AndroidAsync/AndroidAsync into your workspace
- Import all the ion projects (ion/ion, ion/ion-sample) into your workspace.
Projects using ion
There's hundreds of apps using ion. Feel free to contact me or submit a pull request to add yours to this list.
Top Related Projects
Square’s meticulous HTTP client for the JVM, Android, and GraalVM.
A type-safe HTTP client for Android and the JVM
An image loading and caching library for Android focused on smooth scrolling
An Android library for managing images and the memory they use.
An asynchronous, callback-based Http client for Android built on top of Apache's HttpClient libraries.
Convert designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot