简体   繁体   English

将ListView图像存储在缓存中

[英]Storing ListView Images in cache

I have a ListView with more than 100 items and each item has a different image. 我有一个包含100多个项目的ListView,每个项目都有一个不同的图像。 The images are already in the drawable folder, so I'm not requesting to any server. 图像已经在drawable文件夹中,因此我不要求任何服务器。

When I scroll the ListView since the phone has to render each image again, sometimes it gets a little slow, seems like low fps. 当我滚动ListView时,由于手机必须再次渲染每个图像,有时它会变慢一些,似乎是低fps。 For test purposes I used the same image for all items, and the scroll was much better, so I think the problem is indeed the different images needed to being rendered. 出于测试目的,我对所有项目都使用了相同的图像,并且滚动效果要好得多,因此我认为问题确实在于需要渲染不同的图像。

My question is: can I store those images on cache or something to make this scroll smother? 我的问题是:我可以将这些图像存储在高速缓存中或使滚动更窒息的东西吗? Here is my ListView Adapter code: 这是我的ListView适配器代码:

public class AdapterItens extends BaseAdapter implements ListAdapter {

    private final JSONArray jsonArray;

    static class ViewHolder {
        ImageView itemAvatar;
        TextView itemName;
        TextView itemId;
    }

    public AdapterItens(JSONArray jsonArray) {
        this.jsonArray = jsonArray;
    }

    @Override
    public int getCount() {
        return jsonArray.length();
    }

    @Override
    public JSONObject getItem(int position) {
        return jsonArray.optJSONObject(position);
    }

    @Override
    public long getItemId(int position) {
        JSONObject jsonObject = getItem(position);
        return jsonObject.optLong("id");
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final ViewHolder viewHolder;

        if (convertView == null) {
             final LayoutInflater inflater = LayoutInflater.from(Controller.getContext());
             convertView = inflater.inflate(R.layout.item_layout, parent, false);

             viewHolder = new ViewHolder();
             viewHolder.itemAvatar = (ImageView) convertView.findViewById(R.id.avatar_item);
             viewHolder.itemName = (TextView) convertView.findViewById(R.id.name_item);
             viewHolder.itemId = (TextView) convertView.findViewById(R.id.id_item);

             convertView.setTag(viewHolder);
        } else {
             viewHolder = (ViewHolder) convertView.getTag();
        }

        final JSONObject jsonData = getItem(position);
        viewHolder.itemAvatar.setImageResource(Controller.getContext().getResources().getIdentifier(jsonData.getString("itemAvatar"), "drawable", Controller.getContext().getPackageName()));
        viewHolder.itemName.setText(jsonData.getString("itemName"));
        viewHolder.itemId.setText(jsonData.getString("itemId"));

        return convertView;
    }
}

I suppose the problem is that you parse JSON "on fly". 我想问题是您“即时”解析JSON。 First of all parse JSON into list with objects inside AsyncTask, each object will contain id, name and bitmap. 首先,使用AsyncTask中的对象将JSON解析为列表,每个对象将包含id,name和bitmap。

For example: 例如:

class YourObjectName {
    long id;
    String name;
    Bitmap bitmap;
}

Your code will looks like this: 您的代码将如下所示:

static class ViewHolder {
    ImageView itemAvatar;
    TextView itemName;
    TextView itemId;
}

public ItemsAdapter (List<YourObjectName> yourObjectsList) {
    this.yourObjectsList = yourObjectsList;
}

@Override
public int getCount() {
    return yourObjectsList.size();
}

@Override
public YourObjectName getItem(int position) {
    return yourObjectsList.get(position);
}

@Override
public long getItemId(int position) {
    return yourObjectsList.get(position).id;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    final ViewHolder viewHolder;
    if (convertView == null) {
        final LayoutInflater inflater = LayoutInflater.from(Controller.getContext());
        convertView = inflater.inflate(R.layout.item_layout, parent, false);

        viewHolder = new ViewHolder();
        viewHolder.itemAvatar = (ImageView) convertView.findViewById(R.id.avatar_item);
        viewHolder.itemName = (TextView) convertView.findViewById(R.id.name_item);
        viewHolder.itemId = (TextView) convertView.findViewById(R.id.id_item);

        convertView.setTag(viewHolder);
    } else {
        viewHolder = (ViewHolder) convertView.getTag();
    }

    YourObjectName itemAtPosition = yourObjectsList.get(position);
    viewHolder.itemAvatar.setImageBitmap(itemAtPosition.bitmap);
    viewHolder.itemName.setText(itemAtPosition.name);
    viewHolder.itemId.setText(itemAtPosition.id);

    return convertView;
}

Finally, you can use library like Glide or Picasso to load your pictures in background. 最后,您可以使用Glide或Picasso之类的库在后台加载图片。

Just replace this line with one of this library, and instead bitmap save drawable_id. 只需将此行替换为该库之一,然后将位图保存drawable_id。

viewHolder.itemAvatar.setImageBitmap(itemAtPosition.bitmap);

Glide: https://github.com/bumptech/glide 滑行: https : //github.com/bumptech/glide

Glide.with(context)
      .load(itemAtPosition.drawable_id)
      .resize(width, height)
      .centerCrop()
      .into(viewHolder.itemAvatar);

Picasso: http://square.github.io/picasso/ 毕加索: http//square.github.io/picasso/

Picasso.with(context)
       .load(itemAtPosition.drawable_id)
       .override(width, height)
       .centerCrop()
       .into(viewHolder.itemAvatar);

Also it's highly recommended to use recyclerview instead listview, take a look on the accepted answer. 另外,强烈建议使用recyclerview而不是listview,看一下已接受的答案。 Android Recyclerview vs ListView with Viewholder Android Recyclerview与带有Viewholder的ListView

you can use Universal Image Loader library to Cache your images and clear it when 您可以使用Universal Image Loader库来缓存图像,并在出现以下情况时将其清除

loaded many images to flow your listview : 加载了很多图像来流你的listview:

https://github.com/nostra13/Android-Universal-Image-Loader https://github.com/nostra13/Android-Universal-Image-Loader

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM