I am stuck up at one point. I need suggestions for the same.
I am creating an application which involves json parsing. After the parsing I am getting data which involves event name, event description, event place, event image url and so on. The data is huge. You can imagine facebook kinda stuff.
Now the problem is the data is getting parsed but because the event image is in the form of url, I need to convert it into Bitmap.
I have kept all the process of json parsing and bitmap conversion into one AsyncTask(doInBackground()).
This is taking a lot amount of time. I want something like facebook that the data gets loaded and is shown to the end user but the images load slowly and steadily. (I mean when we scroll facebook, then images don't come up immediately).
I want a similar functionality. I need suggestions.
You can still use an AsyncTask, only you'll need to use two seperate tasks.
One for the loading and parsing of the JSON, and one for the loading of the image.
After parsing the JSON, you'll need to start an AsyncTask for every image you're trying to load, making them all load on their own thread. It will show once the item is done loading.
Here is solution for you https://github.com/nostra13/Android-Universal-Image-Loader
You just pass url and imageview resource to loader, and it handles everithing for you. Also support caching. This library is simple and widly used
This concept is called Lazy Loading (AFAIK). You can use already development ImageLoader for this. It will download Image in Background and once it download it will set as background of ImageView. See Custom Downloader
Related
I have to build some data from a json call and populate an object in Android mobile dev.
The json requires the read of the first url to get a list of data. One of the fields is an url to an image which I need to make a second call to the web using asyncTask to retrieve as a blob and save in the object.
I have the code working to get the first url call using the asyncTask. But as I process each set of data I need to make the second asyncTask call to get the image blob.
Is this possible or maybe I am going about it wrong? Sorry no code snippets.
It is not that tough as you are thinking.Follow the below example to parse image and data from json and display them:
http://www.androidbegin.com/tutorial/android-json-parse-images-and-texts-tutorial/
Create a separate package and copy the ImageLoader.java ,MemoryCache.java ,FileCache.java Utils.java
Then you can set your image within the adapter using the image url as:
ImageLoader imageLoader= new ImageLoader(context);
imageLoader.DisplayImage("the image url", imageview);
You can then reuse the imageloader class again and again throughout your project.
Apart from this you can also use third party apis to download images.
Some of them are Picasso and Glide
Currently I am using Glide.It is very powerful and easy to implement.
As per my understanding you want to display those images or download those images received in first asyncTask. I would suggest you for both purposes to use a library like picaso or fresco.
Over thinking it. I can make 2 http request under same task. Problem solved.
I am designing an Android application targeting >= API 17. I have created a class, DownloadImageTask which extends AsyncTask, and receives a string (URL) and an ImageView as arguments. In it, I am opening an HTTP connection, downloading an image from a URL, and using BitmapFactory to create a Bitmap object from the data, then setting the bitmap to the ImageView. The end result is a populated list of data which is available to the user to scroll through, with images populating as they can.
This appears to be a good design on the surface - but I am concerned that I am putting my app at risk for an OOM condition, or other violation of the user experience rules. I'd like to know if the way I've designed this is correct, or if not, how I should approach this.
Thank you in advance for your help.
Two considerations to your own approach:
You shouldn't pass the ImageView to the async task because in that way you are coupling your view and your service layer. So send to the async task the URL, and onPostExecute method call to Activity which implement an updateView (or the like) method.
About your OOM, you are right. The problem might arise if you use the original bitmaps which could have larger resolution than required. Therefore you should scale down the images you keep in memory.
The last issue might not be difficult if you use a few images otherwise could be problematic. So if you will be working with a lot of images and you are not forced to implement your own version, you should have a look to the existing libraries. Some are already mentioned:
Glide
Picasso
I am using an ArrayAdapter along with ListView to display some images (I use Picasso to help with image handling). The images are initially loaded from the state on the local device. The adapter has ids for the images, which the getView() method of the adapter uses to get the path. If the image is not available locally, the local state returns an URL for the image. If the URL has expired, I need to fetch this from the backend.
If the URL is not expired, I have no issues, as I can either directly provide the path to Picasso or the URL and Picasso will handle everything for me. However, when I need to fetch the URL from the backend, I need to do this asynchronously. After fetching the URL, I tried doing the following but it doesn't seem to work (my getView() will in this case use Picasso with the URL):
adapter.remove(id);
adapter.add(id);
notifyDataSetChanged() doesn't seem to do much as well.
What is the best way to handle this situation? Is there any other way than what I am trying to do with the adapters? I want to delay the URL fetch from the backend as much as possible, basically until the user needs to see the image.
UPDATE: for now, I am replacing the id with a temp_id when the URL is expired and then add the correct id again, when I have the valid URL so that the view gets refreshed.
Have you tried clearing your ArrayList of image urls with myArray.clear()? Not so sure if I get your question or how your code looks like.
But I have issues like this before. What worked for me was to repopulating the adapter completely.
This link should help.
I have a URL which loads about 500 records of data which is taking lot of time to download and display in Listview. I would like use lazy loading to display the data but since when i call the asynchronous task the url gets called and it fetches all the data.but i would like to display first few record and then when scrolled should load the next records.please kindly let me know the logic to acheive this.
Thanks in advance.
there is alooot of solutions to resolve this problem.
I have for my self a couple of them:
1) LazyList this is a good example
2) I use AQuery to resolve the lazy and asynchronous issues.
I thing first create custome listview and when you set data on listview that time this process write in thread.i thing easy way
I currently have a ListView with a custom adapter that gets information describing the content of the rows asynchronously. Part of each row is an image URL, that I'm planning to download asynchronously and then display.
My current plan for a strategy to download these images is:
Keep a cache of soft references to downloaded Bitmap objects.
When a getView() is called and the bitmap is in the cache, set the bitmap for the ImageView directly.
If the bitmap isn't in the cache, start loading it in a separate thread, after the download is complete add it to the cache and call notifyDataSetChanged() on the adapter.
I am also planning to kill pending downloads when the Activity object owning the ListView's onDestroy()-method (Or possibly even in the onPause()-method) is called, but most importantly I want to kill the download of pending images when the row goes off screen. I might only actually cancel the download after a short delay, so it can be resumed without wasting bandwidth if the row comes on-screen quickly again.
I, however, am unsure about a few things:
What is the best way to detect when a row goes off-screen so I can cancel the download?
Is calling notifyDataSetChanged() the best thing to do after the download has completed or is there a better way?
Also any comments on the whole strategy would be appreciated.
I don't think calling notifyDataSetChanged() is really needed... I would do it like that:
store URL as Tag in the view when created/updated
register a listener in downloader thread (async task???) for download keeping reference to the view and the URL
whenever image is downloaded asynchronously, I check TAG in the view and if it matches - i would update the ImageView (important to do it in UI thread, but when using async task, it is given). The image should also be stored on SD card (and every time you request URL you should check if it is not already downloaded).
every time when getView() reuses the view (passed view is not empty) I would check the Tag (old URL), replace it with the new URL and cancel the download of the oldURL.
I think it would be pretty much it (some corner cases might happen)...
I use the getFirstVisible and getLastVisible AdapterView properties to detect the visible rows, and put requests in a fixed size stack.
My project is open source and has a most permissive license, if you want to use it:
https://github.com/tbiehn/Android-Adapter-Image-Loader
-Travis
I found the remote resource managing / fetching in the Foursquared source code to be pretty helpful:
http://code.google.com/p/foursquared/source/browse/main/src/com/joelapenna/foursquared/util/RemoteResourceManager.java
It caches images on disk and handles all 3 of your feature requests. See an adapter for how to use it.
As for canceling a download when a row goes off screen you'll have to handle that yourself