Jamal
Jamal

Reputation: 976

Listview reloading already loaded images using Universal image loader

In my Android project I am showing all images from web service(Url) to ListView for this purpose I have used Universal image loader. After loaded some images in List if I scrolled down then scrolled Up,The already loaded images are reloading again.

 DisplayImageOptions.Builder displayImageOptionsBuilder = new DisplayImageOptions
                    .Builder().cacheOnDisk(true).cacheInMemory(true).considerExifParams(true);


 ImageLoader.getInstance().displayImage(imageUri, imageView,
                  displayImageOptionsBuilder.build());

What I tried

ImageAware imageAware = new ImageViewAware(imageView, false);
            ImageLoader.getInstance().displayImage(imageUri, imageAware,displayImageOptionsBuilder.build());

Even used this code it wouldn't make any changes in ListView reloading

Edited

Adapter Class

@Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final String name = getItem(position);
        View view = convertView;    

        if (view == null) {
            view = createView();
            ViewHolder viewHolder = new ViewHolder();    
            viewHolder.image = (ImageView) view.findViewById(R.id.capsule_media_list_item_thumbnail_1);             
            view.setTag(viewHolder);    
        }

ImageHelper.initImage(viewHolder.image,
                imageUrl,
                R.drawable.vx_loading, loadingImageResource,displayOptionsCustomizer);

return view;
}

 private final DisplayOptionsCustomizer displayOptionsCustomizer = new DisplayOptionsCustomizer() {

        @Override
        public void customizeImageOptions(DisplayImageOptions.Builder displayImageOptionsBuilder) {
            displayImageOptionsBuilder.displayer(new RoundedBitmapDisplayer(ApplicationUtils
                    .dipToPixelsRounded(6, getContext()), 0));
        }
    };    

static class ViewHolder {
        public ImageView image;

    }

ImageHelper.java

public static void initImage(final ImageView imageView, final String imageUri,
                                 final int noImageResource, final int loadingImageResource,
                                 final DisplayOptionsCustomizer displayOptionsCustomizer) {
        if (StringUtils.isNotBlank(imageUri)) {             

            DisplayImageOptions.Builder displayImageOptionsBuilder = new DisplayImageOptions
                    .Builder().cacheOnDisk(true).cacheInMemory(true).considerExifParams(true);
            displayImageOptionsBuilder.showImageOnLoading(loadingImageResource)
                    .showImageOnFail(noImageResource);
            if (displayOptionsCustomizer != null) {
                displayOptionsCustomizer.customizeImageOptions(displayImageOptionsBuilder);
            }


           ImageLoader.getInstance().displayImage(imageUri, imageView,
                   displayImageOptionsBuilder.build());
        } else {
            if (noImageResource != 0) {
                imageView.setImageResource(noImageResource);
            } else {
                imageView.setVisibility(View.GONE);
            }
        }
    }

Edited Adapter class as per Dhir Pratap answer

public class ImagesListAdapter extends ArrayAdapter<String> {

private List imagesList = new ArrayList<String>();
private Context context;
ImageLoader imageLoader;
DisplayImageOptions options;

public ImagesListAdapter(Context context, List<String> imagesList) {
        super(context, -1,imagesList);
        this.imagesList = imagesList;
        this.context = context;
imageLoader = ImageLoader.getInstance();
 options = new DisplayImageOptions.Builder().cacheInMemory(true)
        .cacheOnDisk(true).resetViewBeforeLoading(true)
        .showImageForEmptyUri(fallbackImage)
        .showImageOnFail(fallbackImage)
        .showImageOnLoading(fallbackImage).build();

    }    

@Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final String name = getItem(position);
        View view = convertView;    
 ViewHolder viewHolder;

        if (view == null) {
            view = createView();
            viewHolder = new ViewHolder();    
            viewHolder.image = (ImageView) view.findViewById(R.id.capsule_media_list_item_thumbnail_1);             
            view.setTag(viewHolder);    
        }
else{

viewHolder =  (ViewHolder) view.getTag(viewHolder); 
}

/*ImageHelper.initImage(viewHolder.image,
                imageUrl,
             R.drawable.vx_loading, loadingImageResource,displayOptionsCustomizer);*/

imageLoader.displayImage(imageUrl,viewHolder.image,
           options);

return view;
}

/* private final DisplayOptionsCustomizer displayOptionsCustomizer = new DisplayOptionsCustomizer() {

        @Override
        public void customizeImageOptions(DisplayImageOptions.Builder displayImageOptionsBuilder) {
            displayImageOptionsBuilder.displayer(new RoundedBitmapDisplayer(ApplicationUtils
                    .dipToPixelsRounded(6, getContext()), 0));
        }
    };   */ 

static class ViewHolder {
        public ImageView image;

    }

}

Upvotes: 6

Views: 5887

Answers (2)

Maulik M. Dodia
Maulik M. Dodia

Reputation: 95

I have same problem. Putting ApplicationClass.java file in src folder and registering it to manifest file will solve your problem.

Here is both files:

ApplicationClass.java

package yourPackageName;

import android.app.Application;

import com.nostra13.universalimageloader.cache.memory.impl.WeakMemoryCache;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import com.nostra13.universalimageloader.core.assist.ImageScaleType;
import com.nostra13.universalimageloader.core.display.FadeInBitmapDisplayer;

public class ApplicationClass extends Application 
{
    @Override
    public void onCreate() {
        super.onCreate();

        // UNIVERSAL IMAGE LOADER SETUP
        DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder().cacheOnDisc(true).cacheInMemory(true)
                .imageScaleType(ImageScaleType.EXACTLY).displayer(new FadeInBitmapDisplayer(300)).build();

        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
                .defaultDisplayImageOptions(defaultOptions).memoryCache(new WeakMemoryCache())
                .discCacheSize(100 * 1024 * 1024).build();

        ImageLoader.getInstance().init(config);
        // END - UNIVERSAL IMAGE LOADER SETUP
    }
}

Manifest file:

    <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="yourPackageName">

    <!--Permissions -->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <application
     android:name="com.webcluesinfotech.loadimagefromurlinlistview.ApplicationClass"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Hope this will help you.

Upvotes: 0

Dhir Pratap
Dhir Pratap

Reputation: 1188

There are few fixes you can do

  1. Your view holder is almost useless. You have to use it as follow

    ViewHolder viewHolder;
    if (view == null) {
        viewHolder = new ViewHolder();    
        viewHolder.image = (ImageView) view.findViewById(R.id.capsule_media_list_item_thumbnail_1);             
        view.setTag(viewHolder);    
    }else{
     viewHolder =  view.getTag(viewHolder); 
    }
    
  2. You should declare the ImageLoader and DisplayImageOptions instance only once. Probably in constructor.

    ImageLoader imageLoader = ImageLoader.getInstance();
    DisplayImageOptions options = new DisplayImageOptions.Builder().cacheInMemory(true)
            .cacheOnDisc(true).resetViewBeforeLoading(true)
            .showImageForEmptyUri(fallbackImage)
            .showImageOnFail(fallbackImage)
            .showImageOnLoading(fallbackImage).build();
    
  3. In the get view you simply load the image as follow

Edit: I had not used ImageAware. You have to use like this.

ImageAware imageAware = new ImageViewAware(viewHolder.image, false);
imageLoader.displayImage(imageUri, imageAware,options);

The answer here says that this indeed was an issue with the UIL which was fixed in version 1.9.

Edit 2: I followed the discussion on the issue at Github and found this answer which does manual checking on the image url. It suggests to do the following

//lets prevent "blinking" by "saving URL tag" hack

    if (viewHolder.image.getTag() == null ||
            !viewHolder.image.getTag().equals(imageUri)) {

        //we only load image if prev. URL and current URL do not match, or tag is null

        ImageAware imageAware = new ImageViewAware(viewHolder.image, false);
        imageLoader.displayImage(imageUri, imageAware,options);
        viewHolder.image.setTag(imageUri);
    }

Upvotes: 12

Related Questions