【问题标题】:Listview reloading already loaded images using Universal image loaderListview 使用通用图像加载器重新加载已加载的图像
【发布时间】:2015-03-21 01:34:32
【问题描述】:

在我的 Android 项目中,我显示了从 web service(Url)ListView 的所有图像,为此我使用了 Universal image loader。在列表中加载一些图像后,如果我向下滚动然后向上滚动,已经加载的图像正在重新加载。

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


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

我尝试了什么

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

即使使用此代码,它也不会在 ListView reloading 中进行任何更改

已编辑

适配器类

@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);
            }
        }
    }

根据编辑了适配器类 Dhir Pratap回答

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;

    }

}

【问题讨论】:

  • 您的问题不清楚...您是如何在Adapter的getView中使用ImageLoader的?图像有多大(重要的是图像加载器可以在内存不足时释放缓存的位图 - 所以它必须从磁盘缓存甚至互联网重新加载它(见下一个问题))?服务器是否还使用电子标签(或其他缓存标头)?
  • @Selvin 我也用 Adapter 类的 getView() 方法编辑了我的问题。
  • 图像大小不同,每张图像都有自己的大小。它们可能是 14.1 kb、13.2 kb、27 kb、23.4 kb、11 kb 等。
  • 我的意思是宽度和高度,如果你把 Bitmap 类考虑在内,那么磁盘大小没有任何意义......仍然,最重要的是如果在服务器上启用了缓存

标签: android listview android-listview universal-image-loader


【解决方案1】:

我也有同样的问题。将 ApplicationClass.java 文件放入 src 文件夹并将其注册到清单文件将解决您的问题。

这是两个文件:

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
    }
}

清单文件:

    <?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>

希望这会对你有所帮助。

【讨论】:

    【解决方案2】:

    你可以做的修复很少

    1. 您的视图持有者几乎没用。您必须按照以下方式使用它

      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. 您应该只声​​明一次 ImageLoader 和 DisplayImageOptions 实例。可能在构造函数中。

      ImageLoader imageLoader = ImageLoader.getInstance();
      DisplayImageOptions options = new DisplayImageOptions.Builder().cacheInMemory(true)
              .cacheOnDisc(true).resetViewBeforeLoading(true)
              .showImageForEmptyUri(fallbackImage)
              .showImageOnFail(fallbackImage)
              .showImageOnLoading(fallbackImage).build();
      
    3. 在获取视图中,您只需按如下方式加载图像

    编辑: 我没有使用 ImageAware。你必须这样使用。

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

    The answer 这里说这确实是 UIL 的问题,在 1.9 版中已修复。

    编辑 2: 我在 Github 上关注了这个问题的讨论,发现 this answer 对图像 url 进行手动检查。它建议执行以下操作

    //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);
        }
    

    【讨论】:

    • Dhir Pratap,我已经尝试过您的代码,但问题仍然存在。 cacheOnDisc(true) 方法是 deprecated 所以我也尝试了 cacheOnDisk(true)
    • 你能用更改更新问题,然后我可以进一步查看。
    • 我已经尝试了你所有编辑的答案,但问题仍然存在。最初我使用 UIL 库版本 1.9.2 现在我更新为 1.9.3 但仍然存在加载问题
    • 恐怕我没有主意了。我下载了 UIL 的示例应用程序,发现此问题出现在网格列表中,但正常列表工作正常。在示例代码中,我看到选项有另一个属性设置为.considerExifParams(true)。无论如何,在我们得到正确答案之前,我建议尝试使用其他库,例如 Picasso 或 Ion。我个人使用 Ion 来加载图像和发送网络请求。
    • 像魅力一样工作 +1 :)
    猜你喜欢
    • 2012-08-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-07
    • 1970-01-01
    • 2016-06-23
    • 2013-09-16
    • 1970-01-01
    相关资源
    最近更新 更多