Need help with ion?
Click the “chat” button below for chat support from the developer who created it, or find similar developers for support.

About the developer

6.3K Stars 1.1K Forks Other 847 Commits 336 Opened issues


Android Asynchronous Networking and Image Loading

Services available


Need anything else?

Contributors list

Android Asynchronous Networking and Image Loading




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.


.setCallback(new FutureCallback() {
    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("") .setJsonObjectBody(json) .asJsonObject() .setCallback(new FutureCallback() { @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

.setBodyParameter("goop", "noop")
.setBodyParameter("foo", "bar")

Post multipart/form-data and read JSON with an upload progress bar

.setMultipartParameter("goop", "noop")
.setMultipartFile("archive", "application/zip", new File("/sdcard/"))

Download a File with a progress bar

// have a ProgressBar get updated automatically with the percent
// and a 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/"))
.setCallback(new FutureCallback() {
    public void onCompleted(Exception e, File file) {
        // download done...
        // do stuff with the File or error

Setting Headers

// set the header
.setHeader("foo", "bar")

Load an image into an ImageView

// This is the "long" way to do build an ImageView request... it allows you to set headers, etc.

// 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("");

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


All operations return a custom Future that allows you to specify a callback that runs on completion.

public interface Future extends Cancellable, java.util.concurrent.Future {
     * Set a callback to be invoked when this Future completes.
     * @param callback
     * @return
    public Future setCallback(FutureCallback callback);

Future string = Ion.with(context) .load("") .asString();

Future json = Ion.with(context) .load("") .asJsonObject();

Future file = Ion.with(context) .load("") .write(new File("/sdcard/"));

Future bitmap = Ion.with(context) .load("") .intoImageView(imageView);

Cancelling Requests

Futures can be cancelled by calling .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.get() method that waits for the result of the request, by blocking if necessary.

JsonObject json = Ion.with(context)

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("") .as(new TypeToken>(){}) .setCallback(new FutureCallback>() { @Override public void onCompleted(Exception e, List tweets) { // chirp chirp } }); }


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:

.setLogging("MyLogs", Log.DEBUG)

Log entries will look like this:

D/MyLogs(23153): (0 ms) Executing request.
D/MyLogs(23153): (106 ms) Connecting socket
D/MyLogs(23153): (2985 ms) Response is not cacheable
D/MyLogs(23153): (3003 ms) 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 json1 = Ion.with(activity, "").asJsonObject();
Future json2 = Ion.with(activity, "").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 json1 = Ion.with(activity) .load("") // tag in a custom group .group(jsonGroup) .asJsonObject();

Future json2 = Ion.with(activity) .load("") // use the same custom group as the other json request .group(jsonGroup) .asJsonObject();

Future image1 = Ion.with(activity) .load("") // for this image request, use a different group for images .group(imageGroup) .intoImageView(imageView1);

Future image2 = Ion.with(activity) .load("") // 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("") .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:

.setCallback(new FutureCallback>() {
    public void onCompleted(Exception e, Response result) {
        // print the response code, ie, 200
        // print the String that was downloaded

Get Ion

   (insert latest version)

dependencies {
    compile 'com.koushikdutta.ion:ion:(insert latest version)'
Local Checkout (with AndroidAsync dependency)
git clone git://
git clone 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://
git clone 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.

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.