问题描述
我的问题是,我不知道我是否应该使用多个列表视图或可以动态增长的自定义列表视图项适配器。例如,对于特定的用户,他们可以有多个活动:搜索
- 拍照结果
- 说点什么结果
- 检查结果中
- ...
My problem is that I don't know whether I should use multiple list view or a custom listview item adapter which can grows dynamically. For example, for a particular user, they can have multiple activities:
- Take a picture
- Say something
- Checking in
- ...
显然,这个列表可以成长,如用户做更多的活动。大多数时候,我通常会创建从 BaseAdapter
扩展自定义项目适配器,并使用 ItemHolder
模式如下:
Apparently, this list can grows as the user has done more activities. Most of the time, I often create a custom item adapter which extends from BaseAdapter
and use the ItemHolder
pattern as follows:
public class PlaceItemAdapter extends BaseAdapter {
private Activity context;
private List<Place> places;
private boolean notifyChanged = false;
public PlaceItemAdapter(Activity context, List<Place> places) {
super();
this.context = context;
this.places = places;
}
public int getCount() {
return places.size();
}
public Object getItem(int position) {
return places.get(position);
}
public long getItemId(int position) {
return position;
}
public static class ItemViewHolder {
TextView nameTextView;
TextView typesTextView;
TextView ratingTextView;
ImageView mapIconImageView;
}
public View getView(int position, View convertView, ViewGroup parent) {
ItemViewHolder holder;
LayoutInflater inflater = context.getLayoutInflater();
if (convertView == null) {
convertView = inflater.inflate(R.layout.place_item, null);
holder = new ItemViewHolder();
holder.nameTextView = (TextView) convertView.findViewById(R.id.place_item_xml_textview_name);
holder.typesTextView = (TextView) convertView.findViewById(R.id.place_item_xml_textview_address);
holder.ratingTextView = (TextView) convertView.findViewById(R.id.place_item_xml_textview_rating);
holder.mapIconImageView = (ImageView) convertView.findViewById(R.id.place_item_xml_imageview_location_icon);
convertView.setTag(holder);
}
else {
holder = (ItemViewHolder) convertView.getTag();
}
holder.nameTextView.setText(places.get(position).getName());
holder.typesTextView.setText(places.get(position).getAddress());
holder.ratingTextView.setText(Integer.toString(places.get(position).getRating()));
/*
* This task is time consuming!
* TODO: find a workaround to handle the image
*/
// holder.mapIconImageView.setImageBitmap(DownloadImageHelper.downloadImage(places.get(position).getIconUrl()));
holder.mapIconImageView.setImageResource(R.drawable.adium);
return convertView;
}
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
notifyChanged = true;
}
}
使用这种方法,数量GUI控件是固定的,这意味着我不能让我的列表视图项看起来像下面的图片。
Using this method, the number GUI widgets is fixed which means I can't make my listview item look like the picture below.
public static class ItemViewHolder {
TextView nameTextView;
TextView typesTextView;
TextView ratingTextView;
ImageView mapIconImageView;
}
我最初的方法是创建嵌套一个适配器项目内的动态视图,但它会产生重复的意见。为了避免重复的观点,我已设置 convertView
为空,这意味着每次加载的时候,它会创建一个新的 ItemViewHolder
最终吃了我所有的记忆。 :(所以我怎么会处理这种情况?一个最小工作示例将大大AP preciated。
My initial approach was to create a dynamic view nested inside an adapter item, however it will produce duplicate views. To avoid duplicate view, I have set convertView
to null which means each time it loads, it will create a new ItemViewHolder
which eventually eats up all my memory. :( So how could I handle this situation? A minimal working example would be greatly appreciated.
复制视图
public class FriendFeedItemAdapter extends BaseAdapter {
private List<FriendFeedItem> items;
private Activity context;
private static LayoutInflater inflater;
public ImageLoader imageLoader;
private ItemViewHolder viewHolder;
public FriendFeedItemAdapter(Activity context, List<FriendFeedItem> items) {
this.context = context;
this.items = items;
inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
imageLoader = new ImageLoader(context.getApplicationContext());
}
public int getCount() {
return items.size();
}
public Object getItem(int position) {
return items.get(position);
}
public long getItemId(int position) {
return position;
}
public static class ItemViewHolder {
TableLayout table;
ImageView imageViewUserPicture;
TextView textViewUsername;
TextView textViewWhatUserDo;
TextView textViewWhere;
TextView textViewTime;
ImageView imageViewSnapPictureBox;
TextView textViewWriteOnWallMessageBox;
}
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = inflater.inflate(R.layout.friend_list_feed_item, null);
viewHolder = new ItemViewHolder();
viewHolder.table = (TableLayout) convertView.findViewById(R.id.friend_list_feed_item_xml_tablelayout_table);
viewHolder.imageViewUserPicture = (ImageView) convertView.findViewById(R.id.friend_list_feed_item_xml_imageview_user_picture);
viewHolder.textViewUsername = (TextView) convertView.findViewById(R.id.friend_list_feed_item_xml_textview_username);
viewHolder.textViewWhatUserDo = (TextView) convertView.findViewById(R.id.friend_list_feed_item_xml_textview_what_user_do);
viewHolder.textViewWhere = (TextView) convertView.findViewById(R.id.friend_list_feed_item_xml_textview_where);
viewHolder.textViewTime = (TextView) convertView.findViewById(R.id.friend_list_feed_item_xml_textview_at_what_time);
convertView.setTag(viewHolder);
}
else {
viewHolder = (ItemViewHolder) convertView.getTag();
}
imageLoader.displayImage(items.get(position).getFriendPictureUrl(), viewHolder.imageViewUserPicture);
viewHolder.textViewUsername.setText(items.get(position).getFriendName());
viewHolder.textViewWhere.setText("at " + items.get(position).getPlaceName());
viewHolder.textViewTime.setText("@" + items.get(position).getActivityTime());
if (items.get(position).getChallengeType() == Challenge.Type.CHECK_IN) {
viewHolder.textViewWhatUserDo.setText("has checked in.");
}
else if (items.get(position).getChallengeType() == Challenge.Type.SNAP_PICTURE) {
viewHolder.textViewWhatUserDo.setText("has snap a picture.");
// add picture box
View rowView = inflater.inflate(R.layout.snap_picture_row_item, null);
viewHolder.imageViewSnapPictureBox = (ImageView) rowView.findViewById(R.id.snap_picture_row_item_xml_imageview_picture);
imageLoader.displayImage(items.get(position).getActivitySnapPictureUrl(), viewHolder.imageViewSnapPictureBox);
viewHolder.table.addView(rowView);
}
else if (items.get(position).getChallengeType() == Challenge.Type.WRITE_ON_WALL) {
viewHolder.textViewWhatUserDo.setText("has written a message on wall.");
// add message box
View rowView = inflater.inflate(R.layout.write_on_wall_row_item, null);
viewHolder.textViewWriteOnWallMessageBox = (TextView) rowView.findViewById(R.id.write_on_wall_row_item_xml_textview_wall_message);
viewHolder.textViewWriteOnWallMessageBox.setText(items.get(position).getActivityComment());
viewHolder.table.addView(rowView);
}
else if (items.get(position).getChallengeType() == Challenge.Type.QUESTION_ANSWER) {
viewHolder.textViewWhatUserDo.setText("has answered a question.");
}
else { // Challenge.Type.OTHER
viewHolder.textViewWhatUserDo.setText("has done some other challenges.");
}
return convertView;
}
}
广泛的内存使用
public View getView(int position, View convertView, ViewGroup parent) {
ItemViewHolder holder = null;
LayoutInflater inflater = context.getLayoutInflater();
convertView = inflater.inflate(R.layout.friend_list_feed_item, null);
// create holder
holder = new ItemViewHolder();
// default field
holder.table = (TableLayout) convertView.findViewById(R.id.friend_list_feed_item_xml_tablelayout_table);
holder.imageViewUserPicture = (ImageView) convertView.findViewById(R.id.friend_list_feed_item_xml_imageview_user_picture);
holder.textViewUsername = (TextView) convertView.findViewById(R.id.friend_list_feed_item_xml_textview_username);
holder.textViewWhatUserDo = (TextView) convertView.findViewById(R.id.friend_list_feed_item_xml_textview_what_user_do);
holder.textViewWhere = (TextView) convertView.findViewById(R.id.friend_list_feed_item_xml_textview_where);
holder.textViewTime = (TextView) convertView.findViewById(R.id.friend_list_feed_item_xml_textview_at_what_time);
convertView.setTag(holder);
holder.imageViewUserPicture.setImageURI(items.get(position).getFriendPictureUri());
holder.textViewUsername.setText(items.get(position).getFriendName());
holder.textViewWhere.setText("at " + items.get(position).getPlaceName());
holder.textViewTime.setText("@" + items.get(position).getActivityTime());
if (items.get(position).getChallengeType() == Challenge.Type.CHECK_IN) {
holder.textViewWhatUserDo.setText("has checked in.");
}
else if (items.get(position).getChallengeType() == Challenge.Type.SNAP_PICTURE) {
holder.textViewWhatUserDo.setText("has snap a picture.");
// add picture box
View rowView = inflater.inflate(R.layout.snap_picture_row_item, null);
holder.imageViewSnapPictureBox = (ImageView) rowView.findViewById(R.id.snap_picture_row_item_xml_imageview_picture);
holder.imageViewSnapPictureBox.setImageURI(items.get(position).getActivitySnapPictureUri());
holder.table.addView(rowView);
}
else if (items.get(position).getChallengeType() == Challenge.Type.WRITE_ON_WALL) {
holder.textViewWhatUserDo.setText("has written a message on wall.");
// add message box
View rowView = inflater.inflate(R.layout.write_on_wall_row_item, null);
holder.textViewWriteOnWallMessageBox = (TextView) rowView.findViewById(R.id.write_on_wall_row_item_xml_textview_wall_message);
holder.textViewWriteOnWallMessageBox.setText(items.get(position).getActivityComment());
holder.table.addView(rowView);
}
else if (items.get(position).getChallengeType() == Challenge.Type.QUESTION_ANSWER) {
holder.textViewWhatUserDo.setText("has answered a question.");
}
else { // Challenge.Type.OTHER
holder.textViewWhatUserDo.setText("has done some other challenges.");
}
return convertView;
}
推荐答案
如果您有少数的变异可能(在你的截图,我可以看到2个不同的列表项)您有两种可能的变体:
If you have small number of possible variants (on your screenshots I can see 2 different list items) You have two possible variants:
通过
设置计数href=\"http://developer.android.com/reference/android/widget/BaseAdapter.html#getViewTypeCount%28%29\">this方法,并提供type对于每一个项目 - 您可以使用convertView
Setup count of different types by this method, and provide type for every item - and you can use convertView.
创建元素的全列表项查看和设置的知名度,你不希望在特定的项目去看看。
Create "full" list item view and set visibility for elements, that you don't want to see in particular item.
有些code#2:
public class ListTestActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
List<Element> list = new ArrayList<Element>();
list.add(new Element(0));
list.add(new Element(0));
list.add(new Element(1));
list.add(new Element(0));
list.add(new Element(1));
list.add(new Element(1));
list.add(new Element(0));
list.add(new Element(0));
list.add(new Element(1));
list.add(new Element(1));
list.add(new Element(1));
list.add(new Element(0));
list.add(new Element(0));
list.add(new Element(1));
list.add(new Element(0));
list.add(new Element(0));
((ListView) findViewById(android.R.id.list)).setAdapter(new SampleAdapter(this, list));
}
private class SampleAdapter extends BaseAdapter {
private List<Element> list;
private Context context;
public SampleAdapter(Context context, List<Element> list) {
this.list = list;
this.context = context;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Element getItem(int position) {
return list.get(position);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null)
switch (getItemViewType(position)) {
case 0:
convertView = new CheckBox(context);
break;
default:
convertView = new Button(context);
break;
}
// Output here shows that you can lay on getItemViewType(position) as indicator of convertView type or structure
Log.e("test", getItemViewType(position) + ": " + convertView.getClass().getSimpleName());
return convertView;
}
@Override
public int getItemViewType(int position) {
return getItem(position).type;
}
@Override
public int getViewTypeCount() {
return 2;
}
@Override
public long getItemId(int position) {
return position;
}
}
private class Element {
public int type;
public Element(int type) {
this.type = type;
}
}
}
这篇关于如何在运行时动态视图添加到ListView项?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!