Android: convertView in ListView is always null - android

I want to use ViewHolder pattern in ListView (I know about RecyclerView but I want it in ListView!!!).
I created it but I noticed that convertView in getView() is always null. Each call getView(). What am I doing wrong?
public class ScheduleListAdapter extends BaseAdapter {
private LayoutInflater lInflater;
private List<ScheduleSubject> scheduleListItems;
public ScheduleListAdapter(Context context, List<ScheduleSubject> scheduleListItems) {
this.scheduleListItems = scheduleListItems;
lInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return scheduleListItems.size();
}
#Override
public Object getItem(int position) {
return scheduleListItems.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
private static class ViewHolder {
TextView name, place;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
convertView = lInflater.inflate(R.layout.schedule_item_show, parent, false);
viewHolder = new ViewHolder();
viewHolder.name = (TextView) convertView.findViewById(R.id.schedule_item_name_textView);
viewHolder.place = (TextView) convertView.findViewById(R.id.schedule_item_place_textView);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
ScheduleSubject scheduleListItem = getScheduleListItem(position);
viewHolder.number.setText(String.valueOf(scheduleListItem.getLessonNumber()));
viewHolder.name.setText(scheduleListItem.getName());
viewHolder.place.setText(scheduleListItem.getPlace());
return convertView;
}
public ScheduleSubject getScheduleListItem(int position) {
return ((ScheduleSubject) getItem(position));
}
}

try replacing this line
ViewHolder viewHolder;
with this one :
Holder viewHolder;
and this one :
viewHolder = (ViewHolder) convertView.getTag();
with this one :
viewHolder = (Holder) convertView.getTag();

Related

error when running checkbox in listview android

when i was trying tutorial checkbox in listview theres some error on my adapter
public View getView(int position, View convertView, ViewGroup parent) {
ViewTag viewTag;
if (convertView == null) {
//取得listItem容器 view
convertView = myInflater.inflate(R.layout.list_item_pegawai, null);
//建構listItem內容view
viewTag = new ViewTag(
(TextView) convertView.findViewById(R.id.txt_namapegawai),
(CheckBox) convertView.findViewById(R.id.checkBox_pegawai));
//設置容器內容
convertView.setTag(viewTag);
} else {
viewTag = (ViewTag) convertView.getTag();
}
complete code
public class CustomAdapter extends BaseAdapter {
private Context context;
public static ArrayList<Model> modelArrayList;
public CustomAdapter(Context context, ArrayList<Model> modelArrayList) {
this.context = context;
CustomAdapter.modelArrayList = modelArrayList;
}
#Override
public int getViewTypeCount() {
return getCount();
}
#Override
public int getItemViewType(int position) {
return position;
}
#Override
public int getCount() {
return modelArrayList.size();
}
#Override
public Object getItem(int position) {
return modelArrayList.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder();
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.list_item_select, null, true);
holder.checkBox = convertView.findViewById(R.id.checkBox);
holder.tvName = convertView.findViewById(R.id.textView7);
holder.Tvnumber = convertView.findViewById(R.id.textView8);
convertView.setTag(holder);
} else {
// the getTag returns the viewHolder object set as a tag to the view
holder = (ViewHolder) convertView.getTag();
}
holder.tvName.setText(modelArrayList.get(position).getName());
holder.Tvnumber.setText(modelArrayList.get(position).getPhone());
holder.checkBox.setChecked(modelArrayList.get(position).getSelected());
holder.checkBox.setTag(R.integer.btnplusview, convertView);
holder.checkBox.setTag(position);
holder.checkBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
View tempview = (View) holder.checkBox.getTag(R.integer.btnplusview);
TextView tv = tempview.findViewById(R.id.textView7);
Integer pos = (Integer) holder.checkBox.getTag();
if (modelArrayList.get(pos).getSelected()) {
modelArrayList.get(pos).setSelected(false);
} else {
modelArrayList.get(pos).setSelected(true);
}
}
});
return convertView;
}
private class ViewHolder {
protected CheckBox checkBox;
private TextView tvName;
private TextView Tvnumber;
}
}

ListView Custom Adapter repeat items

Whats wrong with this adapter, when i scroll down i see repeated rows at the bottom and then when scroll up again i see also repeated rows at the top that were not exist before, and the rest of Data items does not appear
the adapter:
public class ClassesListViewAdapter extends BaseAdapter {
private Context mContext;
ArrayList<String> Data = new ArrayList<>();
public ClassesListViewAdapter(Context context, ArrayList<String> data) {
Data = data;
mContext = context;
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getCount() {
return Data.size();
}
private class ViewHolder{
TextView ClassDataTV;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = ((Activity)mContext).getLayoutInflater();
ViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.classes_list_view_item, parent, false);
holder = new ViewHolder();
holder.ClassDataTV = (TextView) convertView.findViewById(R.id.ClassDataTV);
holder.ClassDataTV.setText(Data.get(position));
convertView.setTag(holder);
}else{
holder=(ViewHolder)convertView.getTag();
}
return convertView;
}
}
and here how i use it:
ArrayList<String> v = new ArrayList<>();
v.add("AAAAAAA");
v.add("WWWWWwW");
v.add("VVVVVVV");
v.add("SSSSSSSSS");
v.add("QQQQQQQQQ");
v.add("YYYYYYYY");
v.add("TTTTTTT");
v.add("UUUUUUUUUU");
v.add("zzzzzzzzzzzz");
v.add("CCCCCCCCCC");
v.add("HHHHHHHHHHH");
v.add("IIIIIIIIII");
v.add("PPPPPPPPP");
mListView.setAdapter(new ClassesListViewAdapter(getActivity(), v));
Put following part of your code outside if-block and it will be fixed :
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = ((Activity)mContext).getLayoutInflater();
ViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.classes_list_view_item, parent, false);
holder = new ViewHolder();
holder.ClassDataTV = (TextView) convertView.findViewById(R.id.ClassDataTV);
convertView.setTag(holder);
}else{
holder=(ViewHolder)convertView.getTag();
}
// initialize your view here
holder.ClassDataTV.setText(Data.get(position));
return convertView;
}
The logic behind ViewHolder pattern tells that you should do it in this way. when you scroll some of reference will not created again and else block called so this cause your list not updated as you expected.

how to implement two objects in a single ViewHolder?

I have got two lists, cart and promos. I want both to be displayed in a single viewholder. Is there any way I can do it? this is how I did, but it is not working.
public class CartAdapter extends BaseAdapter {
ArrayList<Cart> list1;
Context context;
public CartAdapter(Context context, ArrayList<Cart> list) {
this.context = context;
this.list1 = list;
}
#Override
public int getCount() {
return list1.size();
}
#Override
public Object getItem(int position) {
return list1.get(position);
}
#Override
public long getItemId(int position) {
return list1.get(position).getProductId();
}
public View getView(final int position, View convertView, ViewGroup parent) {
View row = convertView;
final ViewHolder holder;
if (row == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.cart_item, parent, false);
holder = new ViewHolder(row);
row.setTag(holder);
} else {
holder = (ViewHolder) row.getTag();
}
final Cart cart = list.get(position);
final Promos promo = databaseHandler.getPromosForCart(cart);
holder.tvTitle.setText(cart.getProductName());
holder.tvPrice.setText(cart.getPrice());
holder.etQuantity.setText(cart.getQuantity());
holder.tvPromotion.setVisibility(View.GONE);
if(cart.hasPromotion){
final ViewHolder holder2;
if (row == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(R.layout.cart_item, parent, false);
holder2 = new ViewHolder(row);
row.setTag(holder);
} else {
holder2 = (ViewHolder) row.getTag();
}
if(promo.type().equals("type1"){
holder2.tvTitle.setText(promo.getProductName());
holder2.tvPrice.setVisibility(View.GONE);
holder2.etQuantity.setVisibility(View.GONE);
holder2.tvPromotion.setText(promo.getPromoDetails());
}else{
holder2.tvTitle.setText(promo.getProductName());
holder2.tvPrice.setVisibility(View.GONE);
holder2.etQuantity.(promo.getQuantity());
holder2.etQuantity.setEnabled(false);
holder2.tvPromotion.setText(promo.getPromoDetails());
}
}
}
Class ViewHolder{
.....
ViewHolder(View v){}
}
}
I searched but all answers I got was about using two layouts, and using only one data list. Please help me.

getview is not called in BaseAdapter

I have a problem with my custom adapter. the method getView() is not called. I searched on my friends "google" and "stackoverflow" but anything fix my problem.
public class custom_adapter extends BaseAdapter {
private List<Activities> listData;
private LayoutInflater layoutInflater;
public custom_adapter(Context context,
List<Activities> listActivity) {
this.listData = listActivity;
layoutInflater = layoutInflater.from(context);
Log.v("BaseAdapter", "custom_adapter");
}
#Override
public int getCount() {
Log.v("BaseAdapter - getCount", String.valueOf(listData.size()));
return listData.size();
}
#Override
public Object getItem(int position) {
return listData.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Log.v("BaseAdapter", "getView");
ViewHolder holder;
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.custom_adapter, null);
holder = new ViewHolder();
holder.name = (TextView) convertView.findViewById(R.id.title);
holder.ratingBar = (RatingBar) convertView.findViewById(R.id.averageRatingBarActivitySearch);
holder.imageView = (ImageView) convertView.findViewById(R.id.thumbImage);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Activities newsItem = (Activities) listData.get(position);
holder.name.setText(newsItem.getName());
holder.ratingBar.setRating(newsItem.getAverageMark());
if (holder.imageView != null) {
new ImageDownloaderTask(holder.imageView).execute(newsItem.getPictureActivityString());
}
return convertView;
}
public static class ViewHolder {
TextView name;
RatingBar ratingBar;
ImageView imageView;
}
}
Furthermore, GetCount is not null !
I will be very glade if you can help me
Regards
K.L
For the purpose of handling List of some objects, extending generic ArrayAdapter may be better choice instead of just BaseAdapter. It will handle a lot of things for you. Your whole adapter class could look like.
public class ActivitiesAdapter extends ArrayAdapter<Activities>
{
private LayoutInflater layoutInflater;
public ActivitiesAdapter(Context context, List<Activities> objects)
{
super(context, 0, objects);
layoutInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Log.v("BaseAdapter", "getView");
ViewHolder holder;
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.custom_adapter, null);
holder = new ViewHolder();
holder.name = (TextView) convertView.findViewById(R.id.title);
holder.ratingBar = (RatingBar) convertView.findViewById(R.id.averageRatingBarActivitySearch);
holder.imageView = (ImageView) convertView.findViewById(R.id.thumbImage);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Activities newsItem = getItem(position);
holder.name.setText(newsItem.getName());
holder.ratingBar.setRating(newsItem.getAverageMark());
if (holder.imageView != null) {
new ImageDownloaderTask(holder.imageView).execute(newsItem.getPictureActivityString());
}
return convertView;
}
public static class ViewHolder {
TextView name;
RatingBar ratingBar;
ImageView imageView;
}
}
and of course you have to set this adapter to your ListView instance. Like
ActivitiesAdapter adapter = new ActivitiesAdapter(this, yourActivitiesList);
ListView listView = (ListView)findViewById(R.id.my_list_id);
listView.setAdapter(adapter);
or simply setListAdapter(adapter); if you are using ListActivity or ListFragment;
I had the same problem. Maybe, the problem is that you don't notify your adapter that you've changed data in the adapter. Try this code in your adapter:
#Override
public int getCount() {
return data.size();
}
And call notifyDataSetChanged(); when you change the data in Adapter.

List items position repeating in getview

I am creating a custom list view using baseadapter.i have 10 list item in my list.my problem is that afetr 6 items ,the first 4 are repeating.i just printed position values in getview.it gives 0,1,2,3,4,5,6,7,8,9,0,1,2,3.My code is below.
thanx in advance
public class ProductListAdapter extends BaseAdapter implements OnClickListener{
/*
* developer :sanu
* date :10-4-2013
* time :3.34 pm
*/
public View row;
private String[] productName;
private String[] producttype;
private String[] priceRangeFrom;
private String[] priceRangeTo;
private String[] productImage;
private Activity activity;
private static LayoutInflater inflater=null;
static String posClicked;
ViewHolder holder;
Integer height1;
Integer width1;
Typeface tf;
Integer FirmaCount;
public ImageLoader imageLoader;
public ProductListAdapter(Activity a,String[] name,String[] type,String[] price_from,String[] price_to,String[] image,Typeface tf) {
activity = a;
productName = name;
producttype = type;
priceRangeFrom = price_from;
priceRangeTo = price_to;
productImage = image;
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
imageLoader=new ImageLoader(activity.getApplicationContext());
}
public int getCount() {
return productName.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public int getViewTypeCount (int position)
{
return position;
}
public static class ViewHolder{
public TextView nameProduct;
public TextView typeProduct;
public TextView priceRangeProduct;
public ImageView productImage;
public ImageView plusImage;
public RelativeLayout mainLayout;
public int position;
}
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null){
convertView = inflater.inflate(R.layout.product_list_details,parent, false);
holder=new ViewHolder();
holder.nameProduct =(TextView)convertView.findViewById(R.id.name);
holder.typeProduct =(TextView)convertView.findViewById(R.id.product);
holder.priceRangeProduct =(TextView)convertView.findViewById(R.id.pricerange);
holder.productImage =(ImageView)convertView.findViewById(R.id.image);
holder.plusImage =(ImageView)convertView.findViewById(R.id.dot);
holder.mainLayout = (RelativeLayout)convertView.findViewById(R.id.mainlayout);
holder.nameProduct.setText(productName[position]);
if(producttype[position].length()>18)
{
holder.typeProduct.setText(producttype[position].substring(0,18)+"...");
}
else
{
holder.typeProduct.setText(producttype[position]);
}
holder.priceRangeProduct.setText(priceRangeFrom[position].substring(0,priceRangeFrom[position].length()-2)+" To "+priceRangeTo[position].substring(0, priceRangeTo[position].length()-2));
imageLoader.DisplayImage(productImage[position], holder.productImage);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder)convertView.getTag();
}
holder.plusImage.setTag(Integer.toString(position));
holder.plusImage.setOnClickListener(this);
holder.mainLayout.setTag(Integer.toString(position));
holder.mainLayout.setOnClickListener(this);
return convertView;
}
This sounds like a case of View re-cyclcing. Android will pass a pre-populated view to the getView method. It does so to minimize object creation. When an existing row-view is scrolled off screen, Android might try to recycle that view to display a row that is now on-screen. You need to account for the fact that this view may have been used to display data for another row (which is now off screen).
You have the following line
holder.typeProduct.setText
within the following conditional:
if(convertView == null){
Move that line outside of the conditional, and all should be well.
It's like EJK said. You are not recycling your view correctly. Change your code to this and notice where I put the setText calls
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null){
convertView = inflater.inflate(R.layout.product_list_details,parent, false);
holder=new ViewHolder();
holder.nameProduct =(TextView)convertView.findViewById(R.id.name);
holder.typeProduct =(TextView)convertView.findViewById(R.id.product);
holder.priceRangeProduct =(TextView)convertView.findViewById(R.id.pricerange);
holder.productImage =(ImageView)convertView.findViewById(R.id.image);
holder.plusImage =(ImageView)convertView.findViewById(R.id.dot);
holder.mainLayout = (RelativeLayout)convertView.findViewById(R.id.mainlayout);
convertView.setTag(holder);
}
else
{
holder = (ViewHolder)convertView.getTag();
}
holder.plusImage.setTag(Integer.toString(position));
holder.plusImage.setOnClickListener(this);
holder.mainLayout.setTag(Integer.toString(position));
holder.mainLayout.setOnClickListener(this);
//setText functions are here
holder.nameProduct.setText(productName[position]);
if(producttype[position].length()>18)
{
holder.typeProduct.setText(producttype[position].substring(0,18)+"...");
}
else
{
holder.typeProduct.setText(producttype[position]);
}
holder.priceRangeProduct.setText(priceRangeFrom[position].substring(0,priceRangeFrom[position].length()-2)+" To "+priceRangeTo[position].substring(0, priceRangeTo[position].length()-2));
imageLoader.DisplayImage(productImage[position], holder.productImage);
return convertView;
}
Change your getView to
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null){
convertView = inflater.inflate(R.layout.product_list_details,parent, false);
holder=new ViewHolder();
holder.nameProduct =(TextView)convertView.findViewById(R.id.name);
holder.typeProduct =(TextView)convertView.findViewById(R.id.product);
holder.priceRangeProduct =(TextView)convertView.findViewById(R.id.pricerange);
holder.productImage =(ImageView)convertView.findViewById(R.id.image);
holder.plusImage =(ImageView)convertView.findViewById(R.id.dot);
holder.mainLayout = (RelativeLayout)convertView.findViewById(R.id.mainlayout);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.nameProduct.setText(productName[position]);
if(producttype[position].length()>18)
{
holder.typeProduct.setText(producttype[position].substring(0,18)+"...");
}
else
{
holder.typeProduct.setText(producttype[position]);
}
holder.priceRangeProduct.setText(priceRangeFrom[position].substring(0,priceRangeFrom[position].length()-2)+" To "+priceRangeTo[position].substring(0, priceRangeTo[position].length()-2));
imageLoader.DisplayImage(productImage[position], holder.productImage);
holder.plusImage.setTag(Integer.toString(position));
holder.plusImage.setOnClickListener(this);
holder.mainLayout.setTag(Integer.toString(position));
holder.mainLayout.setOnClickListener(this);
return convertView;
}
Also check this
How ListView's recycling mechanism works
Change getView()
Declare ViewHolder before if (convertView == null)
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.product_list_details,
parent, false);
holder = new ViewHolder();
holder.nameProduct = (TextView) convertView.findViewById(R.id.name);
holder.typeProduct = (TextView) convertView
.findViewById(R.id.product);
holder.priceRangeProduct = (TextView) convertView
.findViewById(R.id.pricerange);
holder.productImage = (ImageView) convertView
.findViewById(R.id.image);
holder.plusImage = (ImageView) convertView.findViewById(R.id.dot);
holder.mainLayout = (RelativeLayout) convertView
.findViewById(R.id.mainlayout);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.nameProduct.setText(productName[position]);
if (producttype[position].length() > 18) {
holder.typeProduct.setText(producttype[position].substring(0, 18)
+ "...");
} else {
holder.typeProduct.setText(producttype[position]);
}
holder.priceRangeProduct.setText(priceRangeFrom[position].substring(0,
priceRangeFrom[position].length() - 2)
+ " To "
+ priceRangeTo[position].substring(0,
priceRangeTo[position].length() - 2));
imageLoader.DisplayImage(productImage[position], holder.productImage);
holder.plusImage.setTag(Integer.toString(position));
holder.plusImage.setOnClickListener(this);
holder.mainLayout.setTag(Integer.toString(position));
holder.mainLayout.setOnClickListener(this);
return convertView;
}

Categories

Resources