-2

i get a fragment with listview inside another fragment,and the listview have a viewholder class like this:
private class ViewHolder{ TextView rowText1; TextView rowText2; }

and give the textview very simple task:

holder.rowText1.setText(someString); holder.rowText2.setText(someString);

The Log give me a nullpointer error:

java.lang.NullPointerException:
Attempt to invoke virtual method void android.widget.TextView.setText(java.lang.CharSequence) on a null object reference     

But if i just give one view settext(any one), everything works fine:

holder.rowText1.setText(someString);
//holder.rowText2.setText(someString);

Any ideas why?

My viewholder code:

 public View getView(int position, View convertView, ViewGroup parent) {
        int type = getItemViewType(position);
        ViewHolder holder;
        if(convertView == null){
            holder = new ViewHolder();
            convertView = mInflater.inflate(R.layout.some_layout, parent,false);                          
            switch(type){
                case 1:
                    holder.rowText1 = (TextView) convertView.findViewById(R.id.textView1);                                              
                   break;
                case 2:
                    holder.rowText1  = (TextView) convertView.findViewById(R.id.textView1);
                    holder.rowText2 =(TextView)convertView.findViewById(R.id.textView2);

                    ImageView fileImage = (ImageView)convertView.findViewById(R.id.typeImage);
                    fileImage.setImageDrawable(fileDrawable);
                    break;
            }
            convertView.setTag(holder);
        }else {
           holder = (ViewHolder) convertView.getTag();
        } 

Also,i dug a little bit ,find the problem seems to be in the view recycle stage,somehow when the system began to recycle the view ,with two views,it just doesnt work.

coldspring
  • 21
  • 1
  • What is the problem? Looks like you did not finish writing this question before posting it. – laalto Oct 20 '17 at 11:07
  • sorry, this is my first post, i am trying to make the format right,now the question is finished. – coldspring Oct 20 '17 at 11:11
  • 1
    So you've forgotten to init `rowText2` or it is init with null. Post the code where you set up the view holder. – laalto Oct 20 '17 at 11:12
  • I dont think so,using either of the two is ok,just wrong using both.I post the view holder code – coldspring Oct 20 '17 at 11:24
  • OK, after some looking,i find you are right ,it was due to the reason i put the settext code outside the switch clause,so when in case 1,rowtext2 still want to settext. thanks! – coldspring Oct 21 '17 at 03:33

2 Answers2

1

What about changing your getView to this?

public View getView(int position, View convertView, ViewGroup parent) {
    if(convertView == null){
        convertView = LayoutInflater.from(getContext()).inflate(R.layout.some_layout, parent,false)
        int type = getItemViewType(position);
        ViewHolder holder = new ViewHolder();
            convertView = mInflater.inflate(R.layout.some_layout, parent,false);                          
            switch(type){
                case 1:
                    holder.rowText1 = (TextView) convertView.findViewById(R.id.textView1);                                              
                   break;
                case 2:
                    holder.rowText1  = (TextView) convertView.findViewById(R.id.textView1);
                    holder.rowText2 =(TextView)convertView.findViewById(R.id.textView2);                       
                    ImageView fileImage = (ImageView)convertView.findViewById(R.id.typeImage);
                    fileImage.setImageDrawable(fileDrawable);
                    break;
        }
        convertView.setTag(holder);
    }
    return convertView;
} 

This only does everything once and if the convertView isn't null it will return the already existing view.

For more info regarding adapters, view this: How does the getView() method work when creating your own custom adapter?

Ellisan
  • 563
  • 8
  • 22
  • Can you explain the logic? Isn't the point we should avoid calling inflate everytime? – coldspring Oct 20 '17 at 11:45
  • You aren't inflating it every time but only when convertView is null. Howeveryou can try putting what i have outside the if (except the return) inside of it. Check updated answer – Ellisan Oct 20 '17 at 11:50
  • Thanks for your time, the problem is solved,i didn't initiate properly,i will post the solution as an answer – coldspring Oct 21 '17 at 03:35
0

oK,so i solve the problem,as you can see in my original getview code,it didn'T include settext code.I put it after that,so adjust the code in this way(simply add the settext code):

switch(type){
                case 1:
              holder.rowText1 = (TextView)convertView.findViewById(R.id.textView1);
                holder.rowText1.setText(someString);                                                                                                             
                    break;
                case 2:
                    holder.rowText1  = (TextView) convertView.findViewById(R.id.textView1);
                    holder.rowText2 =(TextView)convertView.findViewById(R.id.textView2);                       
                    holder.rowText1.setText(someString);
                   holder.rowText2.setText(someString);
                  ImageView fileImage = (ImageView)convertView.findViewById(R.id.typeImage);
                fileImage.setImageDrawable(fileDrawable);
                    break;
            }

As you can see,because i only want to have one textview in case 1,when i put the settext code outside the switch clause,even in case 1,it still want to execute settext to rowtext2.it is a pretty dumb mistake,newbie spotted!!

coldspring
  • 21
  • 1