-1

This question was asked here: Universal-Image-Loader: wrong Bitmaps are attached to ImageView

I am using the the latest, 1.9.3. I implemented the solution by having this in my application class:

@Override
public void onCreate() {
    super.onCreate();

    DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder().resetViewBeforeLoading(true).build();
    ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
        .defaultDisplayImageOptions(defaultOptions)
        .build();
    ImageLoader.getInstance().init(config);
}

Per Android-Universal-Image-Loader doesn't keep loaded images on scroll in gridview, I load the image like so in my adapter:

ImageAware imageAware = new ImageViewAware(viewHolder.profileIV, false);
ImageLoader.getInstance().displayImage(imgUrl, imageAware);

It still doesn't work; I'm wondering if it's because I have to make a call to get the image url since the api that supplied the model data did not include an image url.

So in my adapter's getView(), before I use imageloader with the image url, I do another asynch call to get the image url, like so:

 APIclient.getImageJson(getContext(), googleUrl, new JsonHttpResponseHandler() {
        @Override
        public void onSuccess(JSONObject imgJson) {
            try {
                JSONObject responseDataValue = imgJson.getJSONObject("responseData");
                JSONArray resultsValue = responseDataValue.getJSONArray("results");
                JSONObject result = resultsValue.getJSONObject(0);
                String imgUrl = result.getString("url");

                ImageAware imageAware = new ImageViewAware(viewHolder.profileIV, false);
                ImageLoader.getInstance().displayImage(imgUrl, imageAware);
                //ImageLoader.getInstance().displayImage(imgUrl, viewHolder.profileIV);
            }
            catch(Exception e) {
                e.printStackTrace();
            }
        }

google url here looks like: https://ajax.googleapis.com/ajax/services/search/images?rsz=1&start=1&v=1.0&q=%22barack%20obama%22

each row would have a different url since the names are different. I don't know if the problem is still a listview recycer problem that wasn't fixed in the universal image loader library or if the culprit lies in the additional network call. How can I make the thumbnails consistent with the data next to it?

Community
  • 1
  • 1
HukeLau_DABA
  • 2,384
  • 6
  • 33
  • 51
  • Is `APIclient.getImageJson(...)` any library? Can you do JSON requests synchronously? If you do then I can propose you a solution, just write code for sync JSON loading. – nostra13 Sep 08 '14 at 07:59

1 Answers1

-1

I think it's because of async call APIclient.getImageJson(...) in getView(). It's unknown time when onSuccess() callback is fired so you can call ImageLoader.getInstance().displayImage(...) for already recycled ImageView.

I can propose you join these 2 async operations (get JSON by APIclient, load image by ImageLoader) following way. Implement own ImageDoanloader which will process google JSON URLs (https://ajax.googleapis.com/ajax/services/search/images?rsz=1&start=1&v=1.0&q=%22barack%20obama%22), extract image URL and load image.

Let's introduce our own URI scheme - "json". So we know that incoming URIs like "json://..." are correspond to JSON link.

  1. Prepare own downloader:

    public class JsonImageDownloader extends BaseImageDownloader {
    
        public static final String SCHEME_JSON = "json";
        public static final String SCHEME_JSON_PREFIX = SCHEME_JSON + "://";
    
        public JsonImageDownloader(Context context) {
            super(context);
        }
    
        public JsonImageDownloader(Context context, int connectTimeout, int readTimeout) {
            super(context, connectTimeout, readTimeout);
        }
    
        @Override
        public InputStream getStream(String uri, Object extra) throws IOException {
            if (uri.startsWith(SCHEME_JSON_PREFIX)) {
                String jsonUri = uri.substring(SCHEME_JSON_PREFIX.length());
                JSONObject imgJson = APIclient.getImageJson(context, jsonUri); // sync JSON loading
                try {
                    JSONObject responseDataValue = imgJson.getJSONObject("responseData");
                    JSONArray resultsValue = responseDataValue.getJSONArray("results");
                    JSONObject result = resultsValue.getJSONObject(0);
                    String imgUrl = result.getString("url");
                    return super.getStream(imgUrl, extra);
                } catch (JSONException e) {
                    throw new RuntimeException(e);
                }
            } else {
                return super.getStream(uri, extra);
            }
        }
    }
    
  2. Set it into configuration

    ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context)
            .imageDownloader(new JsonImageDownloader(context))
            ....
            .build();
    
  3. Use ImageLoader in getView(...) without using APIclient:

    ImageAware imageAware = new ImageViewAware(viewHolder.profileIV, false);
    ImageLoader.getInstance().displayImage("json://" + googleUrl, imageAware);
    
nostra13
  • 12,377
  • 3
  • 33
  • 43
  • thanks for responding, but isn't it bad practice to make synchronous network calls? It will block the UI. – HukeLau_DABA Nov 07 '14 at 21:44
  • `getStream()` is called on separate thread. There are no network calls on UI thread in my answer. – nostra13 Nov 07 '14 at 23:04
  • APIclient.getImageJson is a network request to get the image url, in your comments you mentioned synchronous, not asynch. You are right about the problem, by the time the asynch request finishes to get the image url. UniversalImageLoader renders that url to a view that doesnt match due to row recycling. – HukeLau_DABA Nov 07 '14 at 23:42
  • So APIclient doesn't have possibility to call `getImageJson()` synchronously? – nostra13 Nov 08 '14 at 10:11
  • If I wanted to get the image json(a network call to get the image json) and block the UI, I could just do that in the adapter getView without doing anything else. That's the heart of the problem, the image url isnt known, so another network call is required to get it. – HukeLau_DABA Nov 08 '14 at 17:10