Git Product home page Git Product logo

ion's Introduction

Android Asynchronous Networking and Image Loading

Download

Features

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

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.

ion's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ion's Issues

Redirect

Need a way to find the final redirect destination after a request completes.

Add DELETE support

DELETE HTTP networking support please.

I know this an async issue but will need to be implemented here as well. I can post in the async issues if you want.

InflaterInputFilter.report does not reference the original exception

I encounter regular failure whle downloading images, bringing me to:
com.koushikdutta.async.http.filter.InflaterInputFilter.report(Exception e)

If mInflater.getRemaining() > 0, could you keep the original exception as cause of the new IOException in such a case ?

Thanks,
Benoit

java.net.SocketException error occured, but did not receive any response from FutureCallback

below error occured when device network is not available.
but did not called FutureCallBack.

----------------------------------------------error--------------------------------------
Unhandled exception
java.net.SocketException: sendto failed: EPIPE (Broken pipe)
at libcore.io.IoBridge.maybeThrowAfterSendto(IoBridge.java:506)
at libcore.io.IoBridge.sendto(IoBridge.java:489)
at java.nio.SocketChannelImpl.writeImpl(SocketChannelImpl.java:369)
at java.nio.SocketChannelImpl.write(SocketChannelImpl.java:346)
at java.nio.channels.SocketChannel.write(SocketChannel.java:423)
at ion.test.async.SocketChannelWrapper.write(SocketChannelWrapper.java:36)
at ion.test.async.AsyncNetworkSocket.write(AsyncNetworkSocket.java:79)
at ion.test.async.Util$7.onWriteable(Util.java:173)
at ion.test.async.Util.writeAll(Util.java:178)
at ion.test.async.Util.writeAll(Util.java:184)
at ion.test.async.http.AsyncHttpResponseImpl.setSocket(AsyncHttpResponseImpl.java:44)
at ion.test.async.http.AsyncHttpClient$3.onConnectCompleted(AsyncHttpClient.java:294)
at ion.test.async.http.AsyncSocketMiddleware$2$2$1.onConnectCompleted(AsyncSocketMiddleware.java:189)
at ion.test.async.AsyncServer.runLoop(AsyncServer.java:824)
at ion.test.async.AsyncServer.run(AsyncServer.java:665)
at ion.test.async.AsyncServer.access$5(AsyncServer.java:654)
at ion.test.async.AsyncServer$14.run(AsyncServer.java:613)

Response Headers

I can not find a way to get the response headers when using Ion.with, specifically trying to get the URI after a redirection and need to access response headers to do that. Instead, the callback you provide only ever gives you the response body in a the format you desire.

Is there a way to access the response headers using Ion? I found a workaround using AsyncHttpClient directly, however then I cannot find a way to provide a post body or post parameters.

Issue with Disk Caching

Hello,

First, it would be helpful to clearly state the the DiskCache is automatically activated.

My issue is that if an image download fails because there is no internet connection (Wifi and 3G deactivated), when the internet connection is reactivated the image is not downloaded: the key is still present in IonBitmapRequestBuilder.ion.bitmapsPending so the download is not retried.

Should I explicitely set a timeout?


Also, is it possible invalidate the cache for a specific URL?

Thanks

Disk caching issue

Hi there,

I use ion in my app to access my server that contains a hash file to check the integrity of my app apk per version and sometimes when I update the hash file for a new version the cache file in ion doesn't get updated correctly result in false positive for a new version.

I call Ion with this method:

    private void checkPackageIntegrity() {
        Ion.with(this, URL).setHandler(null)
                .asString().setCallback(new FutureHashCheck());
    }

I upload the tar of the ion cache directory for your pleasure here http://www.mediafire.com/?ng43rmmt4s1damv

As you can see in the journal file, the file is mark as dirty but somehow it's not updated.

The false positive rate is around 6% BTW and for now my workaround is to delete the cache whenever user upgrades to a new version but if this is a bug inside ION I think it should be fixed.

Make Ion can register custom json deserializer

Hi Koush,

I am working on an app with your awesome library. I found a problem that I cannot register a custom json deserializer and it is so common in json world. You can found the example in [api.dribbble.com] when the api returns a pageable result. They have the same data structure so we can use generic type to represent it. However, the keys of result list are not the same, like shots for Shot, comments for Comment, so I have to write a custom deserializer to deal with it. And I have fixed it in my fork, can I send you a pull request?

ProgressBar not updated in the UI Thread

Sometimes, I get the following stack:
09-02 22:21:37.675: W/System.err(9360): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
09-02 22:21:37.675: W/System.err(9360): at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:5010)
09-02 22:21:37.675: W/System.err(9360): at android.view.ViewRootImpl.invalidateChildInParent(ViewRootImpl.java:996)
09-02 22:21:37.675: W/System.err(9360): at android.view.ViewGroup.invalidateChild(ViewGroup.java:4356)
09-02 22:21:37.675: W/System.err(9360): at android.view.View.invalidate(View.java:10527)
09-02 22:21:37.675: W/System.err(9360): at android.view.View.setFlags(View.java:8582)
09-02 22:21:37.675: W/System.err(9360): at android.view.View.setVisibility(View.java:5651)
09-02 22:21:37.675: W/System.err(9360): at android.widget.ProgressBar.setVisibility(ProgressBar.java:938)
09-02 22:21:37.680: W/System.err(9360): at com.android.internal.policy.impl.PhoneWindow.showProgressBars(PhoneWindow.java:1426)
09-02 22:21:37.680: W/System.err(9360): at com.android.internal.policy.impl.PhoneWindow.updateProgressBars(PhoneWindow.java:1405)
09-02 22:21:37.685: W/System.err(9360): at com.android.internal.policy.impl.PhoneWindow.onIntChanged(PhoneWindow.java:1344)
09-02 22:21:37.685: W/System.err(9360): at com.android.internal.policy.impl.PhoneWindow.updateInt(PhoneWindow.java:3348)
09-02 22:21:37.685: W/System.err(9360): at com.android.internal.policy.impl.PhoneWindow.setFeatureInt(PhoneWindow.java:1289)
09-02 22:21:37.685: W/System.err(9360): at android.app.Activity.setProgress(Activity.java:4720)
09-02 22:21:37.690: W/System.err(9360): at com.actionbarsherlock.internal.ActionBarSherlockNative.setProgress(ActionBarSherlockNative.java:185)
09-02 22:21:37.690: W/System.err(9360): at com.actionbarsherlock.app.SherlockActivity.setSupportProgress(SherlockActivity.java:258)
09-02 22:21:37.690: W/System.err(9360): at blasd.wishset.AWishSetActivity$2.setProgress(AWishSetActivity.java:183)
09-02 22:21:37.690: W/System.err(9360): at blasd.wishset.history.PriceHistoryActivity$10.setProgress(PriceHistoryActivity.java:471)
09-02 22:21:37.690: W/System.err(9360): at com.koushikdutta.ion.IonRequestBuilder$EmitterTransform$2.onData(IonRequestBuilder.java:418)
09-02 22:21:37.690: W/System.err(9360): at com.koushikdutta.async.FilteredDataEmitter.onDataAvailable(FilteredDataEmitter.java:54)
09-02 22:21:37.690: W/System.err(9360): at com.koushikdutta.async.Util.emitAllData(Util.java:20)
09-02 22:21:37.690: W/System.err(9360): at com.koushikdutta.async.FilteredDataEmitter.onDataAvailable(FilteredDataEmitter.java:50)
09-02 22:21:37.690: W/System.err(9360): at com.koushikdutta.async.Util.emitAllData(Util.java:20)
09-02 22:21:37.695: W/System.err(9360): at com.koushikdutta.async.http.filter.InflaterInputFilter.onDataAvailable(InflaterInputFilter.java:54)
09-02 22:21:37.695: W/System.err(9360): at com.koushikdutta.async.http.filter.GZIPInputFilter.onDataAvailable(GZIPInputFilter.java:133)
09-02 22:21:37.695: W/System.err(9360): at com.koushikdutta.async.Util.emitAllData(Util.java:20)
09-02 22:21:37.695: W/System.err(9360): at com.koushikdutta.async.FilteredDataEmitter.onDataAvailable(FilteredDataEmitter.java:50)
09-02 22:21:37.695: W/System.err(9360): at com.koushikdutta.async.http.filter.ContentLengthFilter.onDataAvailable(ContentLengthFilter.java:31)
09-02 22:21:37.695: W/System.err(9360): at com.koushikdutta.async.Util.emitAllData(Util.java:20)
09-02 22:21:37.695: W/System.err(9360): at com.koushikdutta.async.AsyncNetworkSocket.onReadable(AsyncNetworkSocket.java:170)
09-02 22:21:37.700: W/System.err(9360): at com.koushikdutta.async.AsyncServer.runLoop(AsyncServer.java:810)
09-02 22:21:37.700: W/System.err(9360): at com.koushikdutta.async.AsyncServer.run(AsyncServer.java:669)
09-02 22:21:37.700: W/System.err(9360): at com.koushikdutta.async.AsyncServer.access$700(AsyncServer.java:34)
09-02 22:21:37.700: W/System.err(9360): at com.koushikdutta.async.AsyncServer$14.run(AsyncServer.java:617)

It looks like some calls to the ProgressBar are done out of the UI thread. Is this a bug? If not, how can I easily make sure any update to a ProgressBar is done through a UI thread?

Thanks

SSLException error occured when Https Request.

SSLException occured when excute below code. (Under JellyBean OS)

res = engine.wrap(bb, mWriteTmp); //write(ByteBuffer) in AsyncSSLSocketWrapper.java

----------------------SSLException Msg-------------------------
javax.net.ssl.SSLException: Error occured in delegated task:null

Ion and Proguard

Hi,

I just got caught trapped by ProGuard and Ion. I end finding a commented note related to proguard in com.koushikdutta.async.PushParser.getTap

Could you activate these assertions, and document the whole proguard config specific to Ion?

Thanks

Caching issue - missing flush on clean

HI Koush,

I believe this one is really a disk caching issue; it seems we miss a flush after a clean operation.

Add sequentially any number of image from an URL, after restart without internet connection, the last added image won t be loaded and will show the error image.

Fact is there is no flush after the CLEAN step; it seems to be a flush only after DIRTY. Then the last image DIRTY operation flush the previous image CLEAN step, but nothing flush the last image CLEAN step.

Thanks in advance!

Timeout behavior

Hi Koush,

About the timeout, if we don t set the timeout parameter, the AsyncHttpRequest is done with 0 as timeout instead of the default AsyncHttpRequest.DEFAULT_TIMEOUT since IonRequestBuilder.timeoutMilliseconds is initialized with the java default int value.

Is this expected? I guess no as it may lead to infintely blocked requests (which is the behavior of some Socket impl; I did not checked in this case).

Also, could you introduce a way to define a default timeout?

Thanks!

Upload progress

Is it possible for an implementation of ProgressCallBack for uploading of files?

HTTP HEAD Query for Just Headers

I need to be able to perform a HTTP HEAD (not GET/POST) query, to just get the response headers for a URL. Is this possible with Ion currently?

My app deals with all sorts of URLs, and I want to be able to pre-fetch things like the content type, size, modified date, to then decide which Action to handball the URL to.

I can do this already with load() and withResponse(), but this fetches the entire content back, which if large is slow, and unnecessary bandwidth usage.

Thanks.

empty file

Hi
sometimes when uploading using POST to a java server (internal), I have a progress bar showing the upload, and when uploading files 250KB +/- I can see that it starts to upload the file, at 80% it stops for 2 seconds, and then it continues until 100%. then I see on server side that the file is empty. for example:

------------------------------eb03ed93a28c4317adb024dcb1850a3a
Content-Disposition: form-data; name="file"; filename="takephoto.jpg"
)

is this a bug in Ion? I checked and the file exists and has content. also I tried the same file several times, and it happens only sometimes. those times the progress bar stops for 2 seconds (at different moments) and continues. the other times it just uploads the file fast and works. any idea?

Thanks!

Ion image loading is not smooth

Previously we were using Picasso (http://square.github.io/picasso/) library to load, manage and display images.

This is the video that show differences between Ion and Picasso: https://www.dropbox.com/s/ima3rwckwqinp8g/VIDEO0007.mp4

On the left you have N4 with Ion and on the right you have a Galaxy S4 using Picasso.
The code is the same, we've just changed the line of code that is loading the image.

Picasso:

Picasso.with( itemHolder.root.getContext() ).load( imageUrl ).fit().placeholder( R.drawable.placeholder_thumb ).into( itemHolder.image );

Ion:

Ion.with(itemHolder.image)
                .placeholder(R.drawable.placeholder_thumb)
                .load( imageUrl );

itemHolder is private static class that holds all row images/texts and so on

Question about the lrucache and jpegs

Would it be a good idea to keep in the lrucache bytearrays of jpegs and a small cache of bitmaps?

It would often remove the disk access and would increase the cache size by tenfold.

The limitations that would occur would be a reduced size of the bitmap cache and more cpu intensive operations in order to redecode the bitmaps.

What do you think? Would it be too long to redecode? Im wondering if it could be the silver bullet for my case (full width pictures).

Unsupported operation exception

Failed to find provider info for com.google.plus.platform Failed to find provider info
for com.google.plus.platform United States FATAL EXCEPTION: main
java.lang.UnsupportedOperationException at
com.koushikdutta.ion.IonDrawable.mutate(IonDrawable.java:296) at
android.widget.ImageView.applyColorMod(ImageView.java:1004) at
android.widget.ImageView.onSetAlpha(ImageView.java:187) at
android.view.ViewGroup.drawChild(ViewGroup.java:1678) at
android.view.ViewGroup.dispatchDraw(ViewGroup.java:1437) at
android.view.ViewGroup.drawChild(ViewGroup.java:1708) at
android.view.ViewGroup.dispatchDraw(ViewGroup.java:1437) at
android.widget.AbsListView.dispatchDraw(AbsListView.java:1480) at
android.widget.ListView.dispatchDraw(ListView.java:3229) at
android.view.View.draw(View.java:7083) at
android.widget.AbsListView.draw(AbsListView.java:2588) at
android.view.ViewGroup.drawChild(ViewGroup.java:1710) at

android.view.ViewGroup.dispatchDraw(ViewGroup.java:1437) at
android.view.ViewGroup.drawChild(ViewGroup.java:1708) at
android.view.ViewGroup.dispatchDraw(ViewGroup.java:1437) at
android.view.ViewGroup.drawChild(ViewGroup.java:1708) at
android.view.ViewGroup.dispatchDraw(ViewGroup.java:1437) at
android.view.ViewGroup.drawChild(ViewGroup.java:1708) at
android.view.ViewGroup.dispatchDraw(ViewGroup.java:1437) at
android.view.View.draw(View.java:6974) at
android.widget.FrameLayout.draw(FrameLayout.java:357) at
android.view.ViewGroup.drawChild(ViewGroup.java:1710) at

android.view.ViewGroup.dispatchDraw(ViewGroup.java:1437) at
android.view.ViewGroup.drawChild(ViewGroup.java:1708) at
android.view.ViewGroup.dispatchDraw(ViewGroup.java:1437) at
android.view.ViewGroup.drawChild(ViewGroup.java:1708) at
android.view.ViewGroup.dispatchDraw(ViewGroup.java:1437) at
android.view.ViewGroup.drawChild(ViewGroup.java:1708) at
android.view.ViewGroup.dispatchDraw(ViewGroup.java:1437) at
android.view.ViewGroup.drawChild(ViewGroup.java:1708) at
android.view.ViewGroup.dispatchDraw(ViewGroup.java:1437) at
android.view.View.draw(View.java:6974) at
android.widget.FrameLayout.draw(FrameLayout.java:357) at
com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1929) at
android.view.ViewRoot.draw(ViewRoot.java:1590) at
android.view.ViewRoot.performTraversals(ViewRoot.java:1290) at
android.view.ViewRoot.handleMessage(ViewRoot.java:1939) at
android.os.Handler.dispatchMessage(Handler.java:99) at
android.os.Looper.loop(Looper.java:143) at
android.app.ActivityThread.main(ActivityThread.java:4196) at
java.lang.reflect.Method.invokeNative(Native Method) at
java.lang.reflect.Method.invoke(Method.java:507) at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839) at
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) at
dalvik.system.NativeStart.main(Native Method)

AND

@OverRide
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    ViewHolder holder;
    holder = new ViewHolder();
    View rowView = inflater.inflate(R.layout.list_user_item, parent, false);
    holder.textView = (TextView) rowView.findViewById(R.id.label);
    holder.imageView = (ImageView) rowView.findViewById(R.id.imageView1);
    holder.textView.setText(values.get(position));

    String s = values.get(position);
    String i = imgvalues.get(position);
    scaleImage(rowView);

    Ion.with(context, i)
    .withBitmap()     
    .animateIn(R.anim.fade_in)
    .intoImageView(holder.imageView);


   if( !imgvalues.get(position).contains(".jpg")){
       holder.imageView.setVisibility(View.GONE);
   }

    if (s.contains("*")) {
        String a = s.replace("*","");
        holder.textView.setTextColor(Color.RED);
        holder.textView.setText(a);

    } else if (s.contains("/")) {
        String a = s.replace("/","");
        holder.textView.setTextColor(Color.BLUE);
        holder.textView.setText(a);
    }


    return rowView;
}

ClassCastException - JsonPrimitive cannot be cast to JsonObject

If you use the setJsonObjectBody() and asJsonObject() methods, and the service has a problem and returns something which cannot be cast to JSON, then Ion throws a ClassCastException.

Would it be possible to add in a check for this and pass this error down as the Exception in the Future?

Load Imageview causes UnsupportedOperationException

hi koush,

i'm facing problem loading image on Android 2.3.4.

Ion.with(imageview).load(url);

it doesnt happen on v4.1.1 or 4.3 on my test devices

java.lang.UnsupportedOperationException
at com.koushikdutta.ion.IonDrawable.mutate(IonDrawable.java:296)
at android.widget.ImageView.applyColorMod(ImageView.java:950)
at android.widget.ImageView.onSetAlpha(ImageView.java:191)
at android.view.ViewGroup.drawChild(ViewGroup.java:1707)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1466)
at android.view.ViewGroup.drawChild(ViewGroup.java:1737)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1466)
at android.view.View.draw(View.java:6989)
at android.view.ViewGroup.drawChild(ViewGroup.java:1739)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1466)
at android.view.ViewGroup.drawChild(ViewGroup.java:1737)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1466)
at android.view.ViewGroup.drawChild(ViewGroup.java:1737)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1466)
at android.view.ViewGroup.drawChild(ViewGroup.java:1737)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1466)
at android.view.ViewGroup.drawChild(ViewGroup.java:1737)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1466)
at android.view.ViewGroup.drawChild(ViewGroup.java:1737)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1466)
at android.view.View.draw(View.java:6989)
at android.widget.FrameLayout.draw(FrameLayout.java:361)
at android.view.ViewGroup.drawChild(ViewGroup.java:1739)
at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1466)
at android.view.View.draw(View.java:6989)
at android.widget.FrameLayout.draw(FrameLayout.java:361)
at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:1882)
at android.view.ViewRoot.draw(ViewRoot.java:1544)
at android.view.ViewRoot.performTraversals(ViewRoot.java:1280)
at android.view.ViewRoot.handleMessage(ViewRoot.java:1882)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3701)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:624)
at dalvik.system.NativeStart.main(Native Method)

[new feature] Load string into TextView wrapper.

Is it possible to write simple wrapper for downloading string into TextView with similar syntax to "Load an image into an ImageView" and features like caching and maybe some placeholder if text failed to download.

Out of memory when loading multiple images into imageview

Dear Koush,
When i load multiple images (from web) into a listview which contains imageviews, i usually end up out of memory exception.
Can you add a feature that scale image's size to equal or under maximum size input (such as 500KB or 1MB size)?
I did use resize but it's not working since imageview.height and width is 0 all the time.
best regards.

[Feature request] optional fadeIn of the image loaded.

From my tests, Ion is the best performing library to load pictures across all devices. ๐Ÿ‘

It is even globally faster than urlImageViewHelper.

I have a small issue with it. In the file IonDrawable.java, in the onDraw method, the fadeIn is hard coded and is not overridden by setAnimationIn().

I want to remove all animations during the loading of my pictures. Would you accept a pull request making the fadeIn optional?

Cant compile?

Ion.with(context, i)
.withBitmap()
.animateIn(R.anim.fade_in)
.intoImageView(imageView);

3 libs added:

ion 1.1.5
async 1.1.5
gson 2.2.4

error:

NoClassDefFoundError com.google.gson.Gson

Tracking the quantity of data downloaded

Hi Koush,

Is there a way to track the quantity of data downloaded through your API ? My goal is to estimate the total bandwidth consumed by my application.

Thanks,
Benoit

Ion.with issues from Ion-1.0.2.jar

When attempting to use Ion, the with function only allows a Context or an ImageView. I also cannot use .as function even when attempting with just a Context.

Also included into my library path:
google-gson-2.2.4
androidasync-1.0.6.jar

Error:
java: no suitable method found for with(com.sampleapp.SampleActivity,java.lang.String)
method com.koushikdutta.ion.Ion.with(android.widget.ImageView) is not applicable
(actual and formal argument lists differ in length)
method com.koushikdutta.ion.Ion.with(android.content.Context) is not applicable
(actual and formal argument lists differ in length)

Specifically with:

Ion.with(this, dev_url)
    .as(new TypeToken < List < Item >> () {})
    .setCallback(new FutureCallback < List < Item >> () {
        @Override
        public void onCompleted(Exception e, List < Item > result) {
            if (e != null) {
                Toast.makeText(SampleActivity.this, "Error downloading items...", Toast.LENGTH_LONG).show();
                return;
            }
            for (int i = 0; i < result.size(); i++) {
                // Add to database
            }
        }
    });

Usage with TextView.setCompoundDrawables

Hi Koush,

I have some difficulty using Ion to fill a CompoundDrawable in a TextView. I usually use .intoImageView to fill automatically an ImageView, but in this case I can inject only a Drawable.

Could you give me a hand? Thanks

CookieStore only populates the first cookie from SharedPreferences

This has something to do with how CookieManager.put() (and in turn how HttpCookie.parse()) works to separate the values from the Map created using headers.toMultiMap() in CookieMiddleware:57

My prefs file is something like this (values changed):

<string name="http://www.macinsiders.com">HTTP/1.1 200 OK
    Cookie: bblastvisit=2375418282; PHPSESSID=58c1c2277718f0378dfa70941df4a338; bblastvisit=2375418282; bblastactivity=0; bbuserid=0001; bbsessionhash=a9653ad70ee96b9ea374fasdasd

</string>

When Ion.getDefault(this) is called, the CookieManager obtained only contains one cookie:

bblastvisit=2375418282

When it should have all 6 of them.

When the cookie is being parsed by HttpCookie.parse(), bblastvisit is detected as a cookie, but all subsequent cookies are detected as attributes for bblastvisit. Of course, those aren't valid attributes so they're discarded and the CookieManager is left with just one cookie: bblastvisit.

onCompleted File is null

hi koush,
i wanted to perform some operation on the File after its downloaded. but i'm getting null for the File object being returned

Ion.with(this, imageUrl)
    .write(new File("/cache/example.jpg"))
    .setCallback(new FutureCallback<File>() {

        @Override
        public void onCompleted(Exception e, File file) {
            //fail at asserting
            Assert.assertNotNull(file);
        }
    });
}

Timeout on upload POST

Hi
I'm setting the timeout to
Ion.with(context, url)....
ion.setTimeout(60 * 60 * 1000);

but I get timouts exception anyway. is the timeout only for receiving data? because I get it when uploading a lot of data, when doing a POST. is there anyway to set the timeout on that case?

TIA!

Ion.with(context, url).asBitmap().setCallback(...) : callback bitmap is always null.

I have a grid view with images loaded using Ion. The adapter's getView() has this line and it works good:

Ion.with(iv).resize(mImageThumbSize, mImageThumbSize).centerCrop().load(url);

Tapping on a grid item opens a viewer fragment with the image's URL as a bundle argument. Now the line in the title attempts to load the URL but its callback always returns null. It used to work fine. I pulled the latest code today and found Ion's behavior is changed. If I give a fresh URL that is never loaded by Ion, the callback works ok. I also observed Ion returns a bitmap correctly if I give a URL of an image loaded by an older build of Ion (I think before 9/5's commit) so I think something is broken (or I need some adustment) in disk cache. Any idea? Thanks.

Problem in API < 9

Hi,

I've a problem with Android 2.2 version (java.net.CookieManager only available at level 9),
java.lang.NoClassDefFoundError: java.net.CookieManager at com.koushikdutta.ion.cookie.CookieMiddleware.(CookieMiddleware.java:27).

Follow a post in another library about same problem: https://github.com/stackmob/StackMob_Android/issues/1

I cloned your branche and ill try fix this problem...

setHostnameVerifier setTrustManagers with Ion

Hi
I want to set:
com.koushikdutta.async.http.AsyncHttpClient.getDefaultInstance().getSSLSocketMiddleware().setHostnameVerifier(new AllowAllHostnameVerifier());
com.koushikdutta.async.http.AsyncHttpClient.getDefaultInstance().getSSLSocketMiddleware().setTrustManagers(new TrustManager[]{new X509TrustManager() {

that Ion will use then... is that possible? I tried it and it doesn't work, is like if I never set them.

Thanks

Setting the HTTP Request Method

I don't know if I am an idiot and missing it, or if it's not in the API somewhere but I cannot find out how to set the HTTP Request Method. In one of my companies API calls, I need to PUT but I cannot figure out how to switch it to PUT from POST. As a result, the API call is failing.

[FutureEnhancement]Load alternative image url on Error

I'm not sure if this is implemented, but on image loading error, it only loads a drawable.

How about on error it tries to load another image url?

For example:

Ion.with(imageview).placeholder(R.drawable.image) .error("http://example.com/error.jpg").load(imageURL);

Thanks in advance.

Upload File using Mutipart is too slow.

i'm uploading image file using multipart.
(Image file is jpg, and size is 3MB)
upload is success but too long time (33 seconds).
Same file uploading using HttpUrlConnection, complete just 3 seconds.

[feature request] Persistent CookieStore support

Or a custom CookieStore support.

Idea being that if we use this CookieStore, the session is resumed when a new instance of the app is started. The cookies would be stored in Shared Preferences.

Something like this class: https://github.com/loopj/android-async-http/blob/master/src/com/loopj/android/http/PersistentCookieStore.java

I tried to implement a custom CookieMiddleware to use a custom CookieStore using this call:

Ion.getDefault(this).getHttpClient().insertMiddleware(middleware);

But when I call:

List<HttpCookie> cookies = Ion.getDefault(context).getCookieMiddleware().getCookieStore().getCookies();

This call doesn't use the custom CookieStore. Am I doing something wrong?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.