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.
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 facing a problem with onItemClickListener. I have a ListView which contains strings as well as two images from parse.com table. I want to show the strings and images (that i have pushed in parse.com database) in another activity after I click on any item. I successfully get all the strings using getIntent() but I'm not able to find the solution to fetch the images from ListView item dynamically.
What is the best way to acomplish this?
In this case, the click event can provide the file Url's string value to another activity via the putExtra
look at the docs for calling $FileObj.'getUrl' that retrieves url as Type string
working with images in persistence you should store both full-sz and thumb-sz, working with the thumb in list-adapter context.
So, if u have store the bitmap for the thumbs file on parse, with "getUrl" you can operate on the URL value of the file( its useful in frameworks like 'Volley')
Read up on using adapters particularly "getView" to load the bitmap whenever you need to provide the bmp to a list adapter from your image lib.
Pass the File-Url-string to new activity in "Extra String Value"
Use Volley for your networking/file retreival and bitmap caching. bit of a guess but Volley and parse should be OK.
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
In my Android app, I am making a http request, getting some data, putting it in my local sqlite database & then populating a gridview using that data. I have the code working for an activity but I need to use fragment now to get this done as there are many similar pages to be shown. I read that using Loader is the best way to deal with data in a fragment.
I am not sure about:
Whether to use CursorLoader, Async taskLoader or SQLiteLoader(developed by commons guy).
In which of the loader functions (onCreateLoader(), onLoadFinished() etc.) do I put my code for making http request, populating the local database & getting the data displayed in a gridview in my fragment
I am also using a lazyload list to show images. How will that fit into the entire thing if I use loader
Can anybody help me with this one? Tried searching for good examples or tutorials but I haven't really found something that's really useful. So, please suggest any if you can. Thanks
Whether to use CursorLoader, Async taskLoader or
SQLiteLoader(developed by commons guy).
CursorLoader is for ContentProviders(which is not your case) and AsyncTaskLoader is the way to go. I haven't use the classes from Commonsware but if they allow overriding of some of their methods then I guess you can use it.
In which of the loader functions (onCreateLoader(), onLoadFinished()
etc.) do I put my code for making http request, populating the local
database & getting the data displayed in a gridview in my fragment
In none of those callbacks because they run(most likely) on the main UI and you must not do network operations in there. The Loader subclasses have the loadInBackground method which runs on a background thread. On this method the Loader queries for data and in which you could place your networks requests and database updating. But you would need to be very careful to not insert duplicate data in the database.
I am also using a lazyload list to show images. How will that fit into
the entire thing if I use loader
As I haven't seen your code, I don't think this two parts are connected. I'm guessing that you use the lazy image loading code directly in the GridView's adapter.
My advice is to not use Loaders for loading and inserting data because their purpose is to only load data on a background thread(having taking care of configuration changes). For your particular situation I would make my own AsyncTaskLoader(or use Commonsware's library) which queries the database for new data. I would then start a new AsyncTask to do the http request and to insert data in the database and then I would trigger a Loader restart in the onPostExecute method of the AsyncTask(with getLoaderManager().restartLoader...). Have a look at this similar question for some problems related to what you're trying to do.
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