Android自定义适配器:ViewHolder抛出java.lang.Nullpointerexception

时间:2016-07-01 21:55:30

标签: android listview nullpointerexception

我有一个活动(ChoozQr2),它在一个单独的类(ChoozQr2Adapter)中显示带有自定义适配器的列表视图。在那个自定义适配器中,我有2个时间戳和一些描述这两个时间选择器之间行为的代码。问题是:此行为仅适用于listview中的最后一项。 我已阅读了几篇文章并尝试最近添加一个视图,但现在它在自定义适配器活动结束时在私有静态类ViewHolder上抛出了一个java.lang.Nullpointerexception(参见2)。

非常感谢您的帮助!

这是我的最后一段代码 1.使用listview调用适配器的活动代码:

public class ChoozQr2 extends Activity implements OnClickListener{
Button fini;    
ListView lv;
Context context;
ChoozQr2Adapter adapter;
ArrayList<String> resultArr;
TextView tvNomDuQr;
NumberPicker npNbJours,OccAlarme;
DatePicker dateFirstOcc;
TimePicker StartTime, StopTime;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.choozqr_step2);

    //declarations
    fini = (Button) findViewById(R.id.fini);

    lv = (ListView) findViewById(R.id.listView1);

    fini.setOnClickListener(this);

    //retrieve data from choozqr
    Bundle b = getIntent().getExtras(); 
    String[] sTemp = b.getStringArray("selectedItems");     
    resultArr = new ArrayList<String>(Arrays.asList(sTemp));

    //set up adapter
    adapter = new ChoozQr2Adapter(this, R.layout.choozqr_step2_textview, resultArr,new BtnClickListener() {
        @Override
        public void onBtnClick(int position) {
            resultArr.add(resultArr.get(position));
            lv.setAdapter(adapter);             
        }
    });

    lv.setAdapter(adapter);
    lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE);  
}
(...)
  1. 自定义适配器代码:

    public class ChoozQr2Adapter extends ArrayAdapter<String> { 
    private final List<String> list;    
    BtnClickListener mClickListener = null; 
    TimePicker StartTime,StopTime;
    DatePicker dateFirstOcc;
    NumberPicker npNbJours, OccAlarme;
    TextView tvNomDuQr;
    Button Btn1,Btn2;
    boolean OccAlarmeNotChanged = true;
    ViewHolder holder;
    
    
    
    public ChoozQr2Adapter(Context context, int resource, List<String> items,BtnClickListener listener) {
        super(context, resource, items);
        list = items;
        mClickListener = listener;
    }
    
    @Override
    public View getView(int position, View convertView, ViewGroup parent) { 
        View v = convertView;
    
        if (v == null) {
            LayoutInflater vi = LayoutInflater.from(getContext());
            v = vi.inflate(R.layout.choozqr_step2_textview, parent, false);
    
            ViewHolder holder = new ViewHolder();    
    
            holder.tvNomDuQr=(TextView)v.findViewById(R.id.NomQr);
            holder.npNbJours=(NumberPicker)v.findViewById(R.id.numberPickerOccurence);
            holder.OccAlarme=(NumberPicker)v.findViewById(R.id.OccAlarme);
            holder.dateFirstOcc=(DatePicker)v.findViewById(R.id.datePicker1erJour);
            holder.StartTime=(TimePicker)v.findViewById(R.id.timePickerHeureDebut);
            holder.StopTime=(TimePicker)v.findViewById(R.id.timePickerHeureFin);
            holder.Btn1=(Button)v.findViewById(R.id.Btn1);
    
            //Btn1      
            holder.Btn1.setTag(position);
            holder.Btn1.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if(mClickListener != null)
                        mClickListener.onBtnClick((Integer) v.getTag());                
                }
            });
    
    
            //initialisations time&date picker
            Calendar now = Calendar.getInstance();
            now.add(Calendar.DAY_OF_MONTH, 1);
            holder.StartTime.setIs24HourView(true);
            holder.StopTime.setIs24HourView(true);  
    
    
            //When StartTime is changed and is equal to stopTime, put the StopTime one hour later
            holder.StartTime.setOnTimeChangedListener(new OnTimeChangedListener(){
                public void onTimeChanged(TimePicker v, int hourOfDay, int minute) {
    
                    ViewHolder holder = (ViewHolder) v.getTag();                
                    holder.StopTime.setCurrentHour(holder.StartTime.getCurrentHour()+1);
                    holder.StopTime.setCurrentMinute(holder.StartTime.getCurrentMinute());
                }});
    
            holder.OccAlarme.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
                @Override
                public void onValueChange(NumberPicker arg0, int arg1, int arg2) {
                    OccAlarmeNotChanged=false;
                }
            });
    
            //When StopTime changes...
            holder.StopTime.setOnTimeChangedListener(new OnTimeChangedListener(){
                public void onTimeChanged(TimePicker v, int hourOfDay, int minute) {
    
                    ViewHolder holder = (ViewHolder) v.getTag();
    
                    //...and is equal to startTime, put the StartTime one hour earlier
                    if(holder.StartTime.getCurrentHour().equals(holder.StopTime.getCurrentHour())){
                        holder.StartTime.setCurrentHour(holder.StartTime.getCurrentHour()+1);
                    }               
    
                    //...and OccAlarme has not been set by user already
                    if(OccAlarmeNotChanged){
                        //Then OccAlarme is updated to half time between start and end time
                        int i = (Math.abs((holder.StartTime.getCurrentHour() - holder.StopTime.getCurrentHour())))*30;
                        holder.OccAlarme.setValue(i);
                        holder.OccAlarme.setMaxValue(2*i);
                    }
                }});            
    
            v.setTag(holder);  // set tag on view           
    
        } else { 
            holder = (ViewHolder) v.getTag();           
        }                       
        return v;
    }    
    private static class ViewHolder {
        private TextView tvNomDuQr;
        private NumberPicker npNbJours;
        private NumberPicker OccAlarme;     
        private TimePicker StartTime;
        private TimePicker StopTime;
        private DatePicker dateFirstOcc;
        private Button Btn1;
        //private Button Btn2;
    }
    }
    
  2. 这是logcat:

    07-02 09:38:22.743: E/AndroidRuntime(20161): FATAL EXCEPTION: main
    07-02 09:38:22.743: E/AndroidRuntime(20161): Process: fr.XXX.XXX, PID: 20161
    07-02 09:38:22.743: E/AndroidRuntime(20161): java.lang.NullPointerException
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at fr.XXX.XXX.ChoozQr2Adapter$ViewHolder.access$12(ChoozQr2Adapter.java:193)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at fr.XXX.XXX.ChoozQr2Adapter$4.onTimeChanged(ChoozQr2Adapter.java:132)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.widget.TimePicker.onTimeChanged(TimePicker.java:656)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.widget.TimePicker.access$300(TimePicker.java:62)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.widget.TimePicker$2.onValueChange(TimePicker.java:167)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.widget.NumberPicker.notifyChange(NumberPicker.java:1835)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.widget.NumberPicker.setValueInternal(NumberPicker.java:1621)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.widget.NumberPicker.scrollBy(NumberPicker.java:1107)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.widget.NumberPicker.onTouchEvent(NumberPicker.java:889)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.View.dispatchTouchEvent(View.java:7837)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2210)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1945)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.widget.NumberPicker.dispatchTouchEvent(NumberPicker.java:946)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2216)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1959)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2075)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1522)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.app.Activity.dispatchTouchEvent(Activity.java:2458)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2023)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.View.dispatchPointerEvent(View.java:8017)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:3966)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3845)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3405)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3455)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3424)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3531)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3432)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3588)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3405)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3455)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3424)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3432)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3405)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5554)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5534)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5505)
    07-02 09:38:22.743: E/AndroidRuntime(20161):    at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:5634)
    

1 个答案:

答案 0 :(得分:0)

问题是视图持有者,因为您多次使用相同的名称,因此只需通过以下代码更改您的适配器,

     public class ChoozQr2Adapter extends ArrayAdapter<String> 
     { 
         private final List<String> list;    
         BtnClickListener mClickListener = null; 
         boolean OccAlarmeNotChanged = true;


         public ChoozQr2Adapter(Context context, int resource, List<String> items,BtnClickListener listener) {
              super(context, resource, items);
              list = items;
              mClickListener = listener;
         }

         @Override
         public View getView(int position, View convertView, ViewGroup parent) { 

          ViewHolder holder = null;
          View v = convertView;

          if (v == null) {
                LayoutInflater vi = LayoutInflater.from(getContext());
               v = vi.inflate(R.layout.choozqr_step2_textview, parent, false);

               holder = new ViewHolder();    

               holder.tvNomDuQr=(TextView)v.findViewById(R.id.NomQr);
               holder.npNbJours=(NumberPicker)v.findViewById(R.id.numberPickerOccurence);
               holder.OccAlarme=(NumberPicker)v.findViewById(R.id.OccAlarme);
               holder.dateFirstOcc=(DatePicker)v.findViewById(R.id.datePicker1erJour);
               holder.StartTime=(TimePicker)v.findViewById(R.id.timePickerHeureDebut);
               holder.StopTime=(TimePicker)v.findViewById(R.id.timePickerHeureFin);
               holder.Btn1=(Button)v.findViewById(R.id.Btn1);               

             v.setTag(holder);  // set tag on view           

           } 
           else { 
             holder = (ViewHolder) v.getTag();           
           }      


    //Btn1      
    holder.Btn1.setTag(position);
    holder.Btn1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if(mClickListener != null)
                mClickListener.onBtnClick((Integer) v.getTag());                
        }
    });


    //initialisations time&date picker
    Calendar now = Calendar.getInstance();
    now.add(Calendar.DAY_OF_MONTH, 1);
    holder.StartTime.setIs24HourView(true);
    holder.StopTime.setIs24HourView(true);  


    //When StartTime is changed and is equal to stopTime, put the StopTime one hour later
    holder.StartTime.setOnTimeChangedListener(new OnTimeChangedListener(){
        public void onTimeChanged(TimePicker v, int hourOfDay, int minute) {

            ViewHolder selectedHolder = (ViewHolder) v.getTag();                
            selectedHolder.StopTime.setCurrentHour(selectedHolder.StartTime.getCurrentHour()+1);
            selectedHolder.StopTime.setCurrentMinute(selectedHolder.StartTime.getCurrentMinute());
        }});

    holder.OccAlarme.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
        @Override
        public void onValueChange(NumberPicker arg0, int arg1, int arg2) {
            OccAlarmeNotChanged=false;
        }
    });

    //When StopTime changes...
    holder.StopTime.setOnTimeChangedListener(new OnTimeChangedListener(){
        public void onTimeChanged(TimePicker v, int hourOfDay, int minute) {

            ViewHolder selectedHolder = (ViewHolder) v.getTag();

            //...and is equal to startTime, put the StartTime one hour earlier
            if(selectedHolder.StartTime.getCurrentHour().equals(selectedHolder.StopTime.getCurrentHour())){
                selectedHolder.StartTime.setCurrentHour(selectedHolder.StartTime.getCurrentHour()+1);
            }               

            //...and OccAlarme has not been set by user already
            if(OccAlarmeNotChanged){
                //Then OccAlarme is updated to half time between start and end time
                int i = (Math.abs((selectedHolder.StartTime.getCurrentHour() - selectedHolder.StopTime.getCurrentHour())))*30;
                selectedHolder.OccAlarme.setValue(i);
                selectedHolder.OccAlarme.setMaxValue(2*i);
            }
        }});      

    return v;
 }    

    private static class ViewHolder
    {
        private TextView tvNomDuQr;
        private NumberPicker npNbJours;
        private NumberPicker OccAlarme;     
        private TimePicker StartTime;
        private TimePicker StopTime;
        private DatePicker dateFirstOcc;
        private Button Btn1;
        //private Button Btn2;
    }
}