Reputation: 1039
I have a ListView with more than 100 items and each item has a different image. The images are already in the drawable folder, so I'm not requesting to any server.
When I scroll the ListView since the phone has to render each image again, sometimes it gets a little slow, seems like low 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:
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;
}
}
Upvotes: 0
Views: 135
Reputation: 891
I suppose the problem is that you parse JSON "on fly". First of all parse JSON into list with objects inside AsyncTask, each object will contain id, name and 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.
Just replace this line with one of this library, and instead bitmap save drawable_id.
viewHolder.itemAvatar.setImageBitmap(itemAtPosition.bitmap);
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/
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. Android Recyclerview vs ListView with Viewholder
Upvotes: 1
Reputation: 297
you can use Universal Image Loader library to Cache your images and clear it when
loaded many images to flow your listview :
https://github.com/nostra13/Android-Universal-Image-Loader
Upvotes: 0