Android 列表视图中的性能较慢

Android 列表视图中的性能较慢,android,image,listview,android-asynctask,adapter,Android,Image,Listview,Android Asynctask,Adapter,我的Android应用程序出现了一个非常奇怪的问题。简单地说,当我将图像内容放入列表视图项中时,就会出现问题。 例如;假设我有一个片段,布局如下 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width=

我的Android应用程序出现了一个非常奇怪的问题。简单地说,当我将图像内容放入
列表视图项中时,就会出现问题。
例如;假设我有一个
片段
,布局如下

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ListView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@android:id/list" />
</LinearLayout>
你们知道为什么会这样吗?我找不到任何理由,也找不到解决这一问题的办法。 提前谢谢


tl;dr:当我将图像放入
ImageView
时,我的
列表视图的速度非常慢。它们从何而来(ram、磁盘、互联网)似乎并不重要。每当我执行
imageView.setImageBitmap()
imageView.setDrawable()
时,性能会急剧下降,几乎不可能进行滚动。

因为您是从主(UI)线程中的资源加载图像,这就是它看起来不稳定的原因。所以像这样在asynktask中加载图像

public class ListAdapter extends ItemViewHolder<ClipData.Item> {

    @ViewId(R.id.listimage)
    ImageView image;

    @ViewId(R.id.listtitle)
    TextView title;

    @ViewId(R.id.listsubtitle)
    TextView subtitle;

    public BeetListAdapter(View view) {
        super(view);
    }

    @Override
    public void onSetValues(BeetItem item, PositionInfo positionInfo) {
        title.setText(item.getTitle());
        subtitle.setText(item.getLatinname());
        getBitmapFromAsset(item.getFirstImageName(), image);
        getView().setTag(R.id.itemid, item.getId());
    }



    private void getBitmapFromAsset(final String strName,final ImageView imageView)
    {
        new AsyncTask<Void,Void,Bitmap>(){

            @Override
            protected Bitmap doInBackground(Void... voids) {
                try{
                    AssetManager assetManager = getContext().getAssets();
                    InputStream istr = null;
                    try {
                        istr = assetManager.open("images/" + strName + ".jpg");
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                    Bitmap bitmap = BitmapFactory.decodeStream(istr);
                    return bitmap;
                }catch (Throwable e){
                    e.printStackTrace();
                }
                return null;

            }

            @Override
            protected void onPostExecute(Bitmap result) {
                super.onPostExecute(result);
                if(result!=null){
                    image.setImageBitmap(result);
                }
            }
        }.execute();

    }

}
公共类ListAdapter扩展了ItemViewHolder{
@ViewId(R.id.listimage)
图像视图图像;
@视图id(R.id.listtitle)
文本视图标题;
@ViewId(R.id.listsubtitle)
文本视图字幕;
公用列表适配器(视图){
超级(视图);
}
@凌驾
设置值上的公共无效(BeetItem项、PositionInfo PositionInfo){
title.setText(item.getTitle());
subtitle.setText(item.getLatinname());
getBitmapFromAsset(item.getFirstImageName(),image);
getView().setTag(R.id.itemid,item.getId());
}
私有void getBitmapFromAsset(最终字符串strName,最终图像视图)
{
新建异步任务(){
@凌驾
受保护位图doInBackground(无效…无效){
试一试{
AssetManager AssetManager=getContext().getAssets();
InputStream istr=null;
试一试{
istr=assetManager.open(“images/”+strName+“.jpg”);
}捕获(IOE异常){
e、 printStackTrace();
}
位图位图=位图工厂.decodeStream(istr);
返回位图;
}捕获(可丢弃的e){
e、 printStackTrace();
}
返回null;
}
@凌驾
受保护的void onPostExecute(位图结果){
super.onPostExecute(结果);
如果(结果!=null){
image.setImageBitmap(结果);
}
}
}.execute();
}
}

缓存图像如果可能,将其缩小。我可以帮你完成所有这些任务

平心而论,以上这些都没有真正解决我的问题,我决定实施

作为参考,这是我初始化Android Universal Image Loader时使用的配置


没有实现
AsyncTask
,我现在在应用程序中有了非常好的用户体验。

不要硬编码
LruMemoryCache
。因为在某些设备上,您将收到:

Fatal signal 11 (SIGSEGV) at 0x00000010 (code=1)
以下是快速加载图像和滚动列表视图的选项:

DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()
                .cacheInMemory(true)
                .cacheOnDisk(true)
                .bitmapConfig(Bitmap.Config.RGB_565)
                .imageScaleType(ImageScaleType.EXACTLY)
                .build();
        int memClass;
        memClass = ( (ActivityManager)this.getSystemService( Context.ACTIVITY_SERVICE ) )
                .getMemoryClass();
        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
                .defaultDisplayImageOptions(defaultOptions)
                .threadPoolSize(1)//from 1-5
                .denyCacheImageMultipleSizesInMemory()
                .threadPriority(Thread.MAX_PRIORITY)
                .tasksProcessingOrder(QueueProcessingType.LIFO)
//                .tasksProcessingOrder(QueueProcessingType.FIFO) /or this
                .memoryCache(new LruMemoryCache(memClass * 1024 * 1024/8))
                .diskCacheExtraOptions(480, 320, null)
                .build();
        ImageLoader.getInstance() .init(config);

您是否尝试按需要的大小缩放图像?另外,我建议您将图像加载到另一个线程(可能是异步任务)并缓存图像。您正在使用的图像的大小和尺寸是多少?似乎这并不完全是我想要的。图像加载速度非常快,性能也要好得多。但是,适配器会在第一个列表项上随机设置图像,当它随机放置图像后,它会转到下一个列表项,直到所有图像视图都正确设置为止。这不是我预期的行为。谢谢你的建议。你提供的图书馆不是我要找的。是
DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()
            .cacheInMemory(true)
            .cacheOnDisk(true)
            .bitmapConfig(Bitmap.Config.RGB_565)
            .imageScaleType(ImageScaleType.EXACTLY)
            .build();

ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
        .defaultDisplayImageOptions(defaultOptions)
        .threadPoolSize(5)
        .threadPriority(Thread.MAX_PRIORITY)
        .tasksProcessingOrder(QueueProcessingType.FIFO)
        .memoryCache(new LruMemoryCache(2 * 1024 * 1024))
        .diskCacheExtraOptions(480, 320, null)
        .build();

ImageLoader.getInstance().init(config);
Fatal signal 11 (SIGSEGV) at 0x00000010 (code=1)
DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()
                .cacheInMemory(true)
                .cacheOnDisk(true)
                .bitmapConfig(Bitmap.Config.RGB_565)
                .imageScaleType(ImageScaleType.EXACTLY)
                .build();
        int memClass;
        memClass = ( (ActivityManager)this.getSystemService( Context.ACTIVITY_SERVICE ) )
                .getMemoryClass();
        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
                .defaultDisplayImageOptions(defaultOptions)
                .threadPoolSize(1)//from 1-5
                .denyCacheImageMultipleSizesInMemory()
                .threadPriority(Thread.MAX_PRIORITY)
                .tasksProcessingOrder(QueueProcessingType.LIFO)
//                .tasksProcessingOrder(QueueProcessingType.FIFO) /or this
                .memoryCache(new LruMemoryCache(memClass * 1024 * 1024/8))
                .diskCacheExtraOptions(480, 320, null)
                .build();
        ImageLoader.getInstance() .init(config);