{"id":3556,"url":"https://github.com/koush/ion","last_synced_at":"2025-05-13T19:14:01.220Z","repository":{"id":8582558,"uuid":"10214538","full_name":"koush/ion","owner":"koush","description":"Android Asynchronous Networking and Image Loading","archived":false,"fork":false,"pushed_at":"2024-02-01T19:55:49.000Z","size":11832,"stargazers_count":6280,"open_issues_count":340,"forks_count":1037,"subscribers_count":326,"default_branch":"master","last_synced_at":"2025-04-28T01:46:10.128Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/koush.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"koush","patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2013-05-22T07:41:23.000Z","updated_at":"2025-04-21T18:12:54.000Z","dependencies_parsed_at":"2024-06-18T15:40:26.411Z","dependency_job_id":null,"html_url":"https://github.com/koush/ion","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/koush%2Fion","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/koush%2Fion/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/koush%2Fion/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/koush%2Fion/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/koush","download_url":"https://codeload.github.com/koush/ion/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254010813,"owners_count":21998995,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-01-05T20:16:44.856Z","updated_at":"2025-05-13T19:14:01.203Z","avatar_url":"https://github.com/koush.png","language":"Java","funding_links":["https://github.com/sponsors/koush"],"categories":["Libraries","CN","Java","Networking","Image Loader","Libs","Image loaders","Index","Uncategorized","库"],"sub_categories":["Networking","[Koushik Dutta](https://github.com/koush)","\u003cA NAME=\"Image_Loading\"\u003e\u003c/A\u003eImage Loading","Uncategorized","[](https://github.com/JStumpp/awesome-android/blob/master/readme.md#networking)网络"],"readme":"*Android Asynchronous Networking and Image Loading*\n\n![](ion-sample/ion-sample.png)\n\n#### Download\n * [Maven](https://github.com/koush/ion#get-ion)\n * [Git](https://github.com/koush/ion#get-ion)\n\n#### Features\n * [Kotlin coroutine/suspend support](https://github.com/koush/AndroidAsync/blob/master/AndroidAsync-Kotlin/README.md)\n * Asynchronously download:\n   * [Images](https://github.com/koush/ion#load-an-image-into-an-imageview) into ImageViews or Bitmaps (animated GIFs supported too)\n   * [JSON](https://github.com/koush/ion#get-json) (via [Gson](https://code.google.com/p/google-gson/))\n   * Strings\n   * [Files](https://github.com/koush/ion#download-a-file-with-a-progress-bar)\n   * Java types using [Gson](https://github.com/koush/ion#seamlessly-use-your-own-java-classes-with-gson)\n * Easy to use Fluent API designed for Android\n   * Automatically cancels operations when the calling Activity finishes\n   * Manages invocation back onto the UI thread\n   * All operations return a [Future](https://github.com/koush/ion#futures) and [can be cancelled](https://github.com/koush/ion#cancelling-requests)\n * HTTP POST/PUT:\n   * text/plain\n   * application/json - both [JsonObject](https://github.com/koush/ion#post-json-and-read-json) and [POJO](https://github.com/koush/ion#seamlessly-use-your-own-java-classes-with-gson)\n   * [application/x-www-form-urlencoded](https://github.com/koush/ion#post-applicationx-www-form-urlencoded-and-read-a-string)\n   * [multipart/form-data](https://github.com/koush/ion#post-multipartform-data-and-read-json-with-an-upload-progress-bar)\n * Transparent usage of HTTP features and optimizations:\n   * SPDY and HTTP/2\n   * Caching\n   * Gzip/Deflate Compression\n   * Connection pooling/reuse via HTTP Connection: keep-alive\n   * Uses the best/stablest connection from a server if it has multiple IP addresses\n   * Cookies\n * [View received headers](https://github.com/koush/ion#viewing-received-headers)\n * [Grouping and cancellation of requests](https://github.com/koush/ion#request-groups)\n * [Download progress callbacks](https://github.com/koush/ion#download-a-file-with-a-progress-bar)\n * Supports file:/, http(s):/, and content:/ URIs\n * Request level [logging and profiling](https://github.com/koush/ion#logging)\n * [Support for proxy servers](https://github.com/koush/ion#proxy-servers-like-charles-proxy) like [Charles Proxy](http://www.charlesproxy.com/) to do request analysis\n * Based on [NIO](http://en.wikipedia.org/wiki/New_I/O) and [AndroidAsync](https://github.com/koush/AndroidAsync)\n * Ability to use [self signed SSL certificates](https://github.com/koush/ion/issues/3)\n\n#### Samples\n\nThe included documented [ion-sample](https://github.com/koush/ion/tree/master/ion-sample) project includes some samples that demo common Android network operations:\n\n * [Twitter Client Sample](https://github.com/koush/ion/blob/master/ion-sample/src/com/koushikdutta/ion/sample/Twitter.java)\n   * Download JSON from a server (twitter feed)\n   * Populate a ListView Adapter and fetch more data as you scroll to the end\n   * Put images from a URLs into ImageViews (twitter profile pictures)\n * File Download with [Progress Bar Sample](https://github.com/koush/ion/blob/master/ion-sample/src/com/koushikdutta/ion/sample/ProgressBarDownload.java)\n * Get JSON and show images with the [Image Search Sample](https://github.com/koush/ion/blob/master/ion-sample/src/com/koushikdutta/ion/sample/ImageSearch.java)\n\n#### More Examples\n\nLooking for more? Check out the examples below that demonstrate some other common scenarios. You can also take a look\nat 30+ ion unit tests in the [ion-test](https://github.com/koush/ion/tree/master/ion/test/src/com/koushikdutta/ion/test).\n\n#### Get JSON\n\n```java\nIon.with(context)\n.load(\"http://example.com/thing.json\")\n.asJsonObject()\n.setCallback(new FutureCallback\u003cJsonObject\u003e() {\n   @Override\n    public void onCompleted(Exception e, JsonObject result) {\n        // do stuff with the result or error\n    }\n});\n```\n\n#### Post JSON and read JSON\n\n```java\nJsonObject json = new JsonObject();\njson.addProperty(\"foo\", \"bar\");\n\nIon.with(context)\n.load(\"http://example.com/post\")\n.setJsonObjectBody(json)\n.asJsonObject()\n.setCallback(new FutureCallback\u003cJsonObject\u003e() {\n   @Override\n    public void onCompleted(Exception e, JsonObject result) {\n        // do stuff with the result or error\n    }\n});\n```\n\n#### Post application/x-www-form-urlencoded and read a String\n\n```java\nIon.with(getContext())\n.load(\"https://koush.clockworkmod.com/test/echo\")\n.setBodyParameter(\"goop\", \"noop\")\n.setBodyParameter(\"foo\", \"bar\")\n.asString()\n.setCallback(...)\n```\n\n#### Post multipart/form-data and read JSON with an upload progress bar\n\n```java\nIon.with(getContext())\n.load(\"https://koush.clockworkmod.com/test/echo\")\n.uploadProgressBar(uploadProgressBar)\n.setMultipartParameter(\"goop\", \"noop\")\n.setMultipartFile(\"archive\", \"application/zip\", new File(\"/sdcard/filename.zip\"))\n.asJsonObject()\n.setCallback(...)\n```\n\n#### Download a File with a progress bar\n\n```java\nIon.with(context)\n.load(\"http://example.com/really-big-file.zip\")\n// have a ProgressBar get updated automatically with the percent\n.progressBar(progressBar)\n// and a ProgressDialog\n.progressDialog(progressDialog)\n// can also use a custom callback\n.progress(new ProgressCallback() {@Override\n   public void onProgress(long downloaded, long total) {\n       System.out.println(\"\" + downloaded + \" / \" + total);\n   }\n})\n.write(new File(\"/sdcard/really-big-file.zip\"))\n.setCallback(new FutureCallback\u003cFile\u003e() {\n   @Override\n    public void onCompleted(Exception e, File file) {\n        // download done...\n        // do stuff with the File or error\n    }\n});\n```\n\n#### Setting Headers\n\n```java\nIon.with(context)\n.load(\"http://example.com/test.txt\")\n// set the header\n.setHeader(\"foo\", \"bar\")\n.asString()\n.setCallback(...)\n```\n\n#### Load an image into an ImageView\n\n```java\n// This is the \"long\" way to do build an ImageView request... it allows you to set headers, etc.\nIon.with(context)\n.load(\"http://example.com/image.png\")\n.withBitmap()\n.placeholder(R.drawable.placeholder_image)\n.error(R.drawable.error_image)\n.animateLoad(spinAnimation)\n.animateIn(fadeInAnimation)\n.intoImageView(imageView);\n\n// but for brevity, use the ImageView specific builder...\nIon.with(imageView)\n.placeholder(R.drawable.placeholder_image)\n.error(R.drawable.error_image)\n.animateLoad(spinAnimation)\n.animateIn(fadeInAnimation)\n.load(\"http://example.com/image.png\");\n```\n\nThe Ion Image load API has the following features:\n * Disk and memory caching\n * Bitmaps are held via weak references so memory is managed very efficiently\n * ListView Adapter recycling support\n * Bitmap transformations via the .transform(Transform)\n * Animate loading and loaded ImageView states\n * [DeepZoom](http://www.youtube.com/watch?v=yIMltNEAKZY) for extremely large images\n\n#### Futures\n\n_All_ operations return a custom [Future](http://developer.android.com/reference/java/util/concurrent/Future.html) that allows\nyou to specify a callback that runs on completion.\n\n```java\npublic interface Future\u003cT\u003e extends Cancellable, java.util.concurrent.Future\u003cT\u003e {\n    /**\n     * Set a callback to be invoked when this Future completes.\n     * @param callback\n     * @return\n     */\n    public Future\u003cT\u003e setCallback(FutureCallback\u003cT\u003e callback);\n}\n\nFuture\u003cString\u003e string = Ion.with(context)\n.load(\"http://example.com/string.txt\")\n.asString();\n\nFuture\u003cJsonObject\u003e json = Ion.with(context)\n.load(\"http://example.com/json.json\")\n.asJsonObject();\n\nFuture\u003cFile\u003e file = Ion.with(context)\n.load(\"http://example.com/file.zip\")\n.write(new File(\"/sdcard/file.zip\"));\n\nFuture\u003cBitmap\u003e bitmap = Ion.with(context)\n.load(\"http://example.com/image.png\")\n.intoImageView(imageView);\n```\n\n#### Cancelling Requests\n\nFutures can be cancelled by calling .cancel():\n\n```java\nbitmap.cancel();\njson.cancel();\n```\n\n#### Blocking on Requests\n\nThough you should try to use callbacks for handling requests whenever possible, blocking on requests is possible too.\nAll Futures have a Future\u003cT\u003e.get() method that waits for the result of the request, by blocking if necessary.\n\n```java\nJsonObject json = Ion.with(context)\n.load(\"http://example.com/thing.json\").asJsonObject().get();\n```\n\n#### Seamlessly use your own Java classes with [Gson](https://code.google.com/p/google-gson/)\n\n```java\npublic static class Tweet {\n    public String id;\n    public String text;\n    public String photo;\n}\n\npublic void getTweets() throws Exception {\n    Ion.with(context)\n    .load(\"http://example.com/api/tweets\")\n    .as(new TypeToken\u003cList\u003cTweet\u003e\u003e(){})\n    .setCallback(new FutureCallback\u003cList\u003cTweet\u003e\u003e() {\n       @Override\n        public void onCompleted(Exception e, List\u003cTweet\u003e tweets) {\n          // chirp chirp\n        }\n    });\n}\n```\n\n#### Logging\n\nWondering why your app is slow? Ion lets you do both global and request level logging.\n\nTo enable it globally:\n\n```java\nIon.getDefault(getContext()).configure().setLogging(\"MyLogs\", Log.DEBUG);\n```\n\nOr to enable it on just a single request:\n\n```java\nIon.with(context)\n.load(\"http://example.com/thing.json\")\n.setLogging(\"MyLogs\", Log.DEBUG)\n.asJsonObject();\n```\n\nLog entries will look like this:\n\n```\nD/MyLogs(23153): (0 ms) http://example.com/thing.json: Executing request.\nD/MyLogs(23153): (106 ms) http://example.com/thing.json: Connecting socket\nD/MyLogs(23153): (2985 ms) http://example.com/thing.json: Response is not cacheable\nD/MyLogs(23153): (3003 ms) http://example.com/thing.json: Connection successful\n```\n\n#### Request Groups\n\nBy default, Ion automatically places all requests into a group with all the other requests\ncreated by that Activity or Service. Using the cancelAll(Activity) call, all requests\nstill pending can be easily cancelled:\n\n```java\nFuture\u003cJsonObject\u003e json1 = Ion.with(activity, \"http://example.com/test.json\").asJsonObject();\nFuture\u003cJsonObject\u003e json2 = Ion.with(activity, \"http://example.com/test2.json\").asJsonObject();\n\n// later... in activity.onStop\n@Override\nprotected void onStop() {\n    Ion.getDefault(activity).cancelAll(activity);\n    super.onStop();\n}\n```\n\nIon also lets you tag your requests into groups to allow for easy cancellation of requests in that group later:\n\n```java\nObject jsonGroup = new Object();\nObject imageGroup = new Object();\n\nFuture\u003cJsonObject\u003e json1 = Ion.with(activity)\n.load(\"http://example.com/test.json\")\n// tag in a custom group\n.group(jsonGroup)\n.asJsonObject();\n\nFuture\u003cJsonObject\u003e json2 = Ion.with(activity)\n.load(\"http://example.com/test2.json\")\n// use the same custom group as the other json request\n.group(jsonGroup)\n.asJsonObject();\n\nFuture\u003cBitmap\u003e image1 = Ion.with(activity)\n.load(\"http://example.com/test.png\")\n// for this image request, use a different group for images\n.group(imageGroup)\n.intoImageView(imageView1);\n\nFuture\u003cBitmap\u003e image2 = Ion.with(activity)\n.load(\"http://example.com/test2.png\")\n// same imageGroup as before\n.group(imageGroup)\n.intoImageView(imageView2);\n\n// later... to cancel only image downloads:\nIon.getDefault(activity).cancelAll(imageGroup);\n```\n\n#### Proxy Servers (like Charles Proxy)\n\nProxy server settings can be enabled all Ion requests, or on a per request basis:\n\n```java\n// proxy all requests\nIon.getDefault(context).configure().proxy(\"mycomputer\", 8888);\n\n// or... to proxy specific requests\nIon.with(context)\n.load(\"http://example.com/proxied.html\")\n.proxy(\"mycomputer\", 8888)\n.getString();\n```\n\nUsing Charles Proxy on your desktop computer in conjunction with request proxying will prove invaluable for debugging!\n\n![](ion-sample/charles.png)\n\n#### Viewing Received Headers\n\nIon operations return a [ResponseFuture](https://github.com/koush/ion/blob/master/ion/src/com/koushikdutta/ion/future/ResponseFuture.java),\nwhich grant access to response properties via the [Response object](https://github.com/koush/ion/blob/master/ion/src/com/koushikdutta/ion/Response.java).\nThe Response object contains the headers, as well as the result:\n\n```java\nIon.with(getContext())\n.load(\"http://example.com/test.txt\")\n.asString()\n.withResponse()\n.setCallback(new FutureCallback\u003cResponse\u003cString\u003e\u003e() {\n    @Override\n    public void onCompleted(Exception e, Response\u003cString\u003e result) {\n        // print the response code, ie, 200\n        System.out.println(result.getHeaders().code());\n        // print the String that was downloaded\n        System.out.println(result.getResult());\n    }\n});\n```\n\n\n#### Get Ion\n\n##### Maven\n```xml\n\u003cdependency\u003e\n   \u003cgroupId\u003ecom.koushikdutta.ion\u003c/groupId\u003e\n   \u003cartifactId\u003eion\u003c/artifactId\u003e\n   \u003cversion\u003e(insert latest version)\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n##### Gradle\n```groovy\ndependencies {\n    compile 'com.koushikdutta.ion:ion:(insert latest version)'\n}\n````\n\n##### Local Checkout (with [AndroidAsync](https://github.com/koush/AndroidAsync) dependency)\n```\ngit clone git://github.com/koush/AndroidAsync.git\ngit clone git://github.com/koush/ion.git\ncd ion/ion\nant -Dsdk.dir=$ANDROID_HOME release install\n```\nJars are at\n * ion/ion/bin/classes.jar\n * AndroidAsync/AndroidAsync/bin/classes.jar\n\n#### Hack in Eclipse\n```\ngit clone git://github.com/koush/AndroidAsync.git\ngit clone git://github.com/koush/ion.git\n```\n* Import the project from AndroidAsync/AndroidAsync into your workspace\n* Import all the ion projects (ion/ion, ion/ion-sample) into your workspace.\n\n#### Projects using ion\n\nThere's hundreds of apps using ion. Feel free to contact me or submit a pull request to add yours to this list.\n\n* [AllCast](https://play.google.com/store/apps/details?id=com.koushikdutta.cast)\n* [Helium](https://play.google.com/store/apps/details?id=com.koushikdutta.backup)\n* [Repost](https://play.google.com/store/apps/details?id=com.dodgingpixels.repost)\n* [Cloupload](https://play.google.com/store/apps/details?id=de.gidix.cloupload)\n* [Binge](https://play.google.com/store/apps/details?id=com.stfleurs.binge)\n* [PictureCast](https://play.google.com/store/apps/details?id=com.unstableapps.picturecast.app)\n* [Eventius](https://play.google.com/store/apps/details?id=com.eventius.android)\n* [Plume](https://play.google.com/store/apps/details?id=com.levelup.touiteur)\n* [GameRaven](https://play.google.com/store/apps/details?id=com.ioabsoftware.gameraven)\n* [See You There](https://play.google.com/store/apps/details?id=com.maps.wearat\u0026hl=en)\n* [Doogles](https://play.google.com/store/apps/details?id=io.dooglesapp)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkoush%2Fion","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkoush%2Fion","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkoush%2Fion/lists"}