1

我有一个列表视图填写数据表格sqlitedatabase。一个list-view元素包含一个TextView的一个Button和一个复选框。点击按钮显示一个timepicker对话框。从timepickerdialog接受一个时间会启动一个AsyncTask。当我点击按钮时总会创建一个新的AsyncTask。Android的AsyncTask ListView包含按钮onClickListener

现在当我点击第七个List-Item时,第一个列表项被更新。线程可能有错误。

活动:

public class SettingsActivity extends Activity 
{ 
    private static final String TAG = "SettingsActivity"; 
    private ReminderBusAdapter busAdapter; 
    private List<Reminder> reminderGoalsList; 
    private static final int TIME_PICKER_DIALOG = 1; 
    private static final String TIME_FORMAT = "kk:mm"; 
    private Calendar mCalendar; 

    // view elements 
    TextView tvStatus; 
    ListView listViewReminder; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) 
    { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.settings); 

     // fetch required data reminder 
     busAdapter = new ReminderBusAdapter(this); 
     loadSettingsData(); 

     // generate view 
     displayView(); 

     mCalendar = Calendar.getInstance(); 
    } 

    private void loadSettingsData() 
    { 
     Log.i(TAG, "loadSettingsData"); 
     reminderGoalsList = new ArrayList<Reminder>(); 
     reminderGoalsList = busAdapter.receiveReminders(); 

     Iterator<Reminder> iter = reminderGoalsList.iterator(); 
     Log.i(TAG, "iterate through all Reminders fetched from db"); 

     int cnt = 0; 
     while (iter.hasNext()) 
     { 
      cnt++; 
      Log.i(TAG, cnt + "] " + iter.next().toString()); 
     } 
    } 

    private void displayView() 
    { 
     Log.i(TAG, "displayView"); 
     tvStatus = (TextView) findViewById(R.id.settingsTextView); 
     listViewReminder = (ListView) findViewById(R.id.settingsListView); 
     listViewReminder.setAdapter(new SettingsAdapter(this, 
          R.layout.settings_reminder_listview, reminderGoalsList)); 
    } 

    @Override 
    protected Dialog onCreateDialog(int id, Bundle b) 
    { 
     switch (id) 
     { 
      case TIME_PICKER_DIALOG: 
       return showTimePicker(b); 
     } 
     return super.onCreateDialog(id); 
    } 

    private Dialog showTimePicker(final Bundle b) 
    { 
     TimePickerDialog timePicker = new TimePickerDialog(this, 0, 
         new TimePickerDialog.OnTimeSetListener() 
         { 
          @Override 
          public void onTimeSet(TimePicker view, int hourOfDay, int minute) 
          { 
           mCalendar.set(Calendar.HOUR_OF_DAY, hourOfDay); 
           mCalendar.set(Calendar.MINUTE, minute); 

           Reminder rem = (Reminder) b.get("reminder"); 
           Log.i(TAG, rem.toString() + " got from adapter"); 

           SimpleDateFormat dateFormat = new SimpleDateFormat(TIME_FORMAT); 
           String dateForTimeButton = dateFormat.format(mCalendar.getTime()); 

           rem.setTime(dateForTimeButton); 

           new UpdateTimerByBtn().execute(new String[] 
                 { 
                  rem.getTime(), 
                  new String(Integer.toString(rem.getId())) 
                 }); 
          } 
         }, mCalendar.get(Calendar.HOUR_OF_DAY), 
         mCalendar.get(Calendar.MINUTE), true); 
     return timePicker; 
    } 

    class UpdateTimerByBtn extends AsyncTask<String, Integer, String> 
    { 
     @Override 
     protected String doInBackground(String... params) 
     { 
      Log.i(TAG, "Starting AsyncTask " + "UpdateTimerByBtn new time=" 
              + params[0] + " from id= " + params[1]); 

      busAdapter.updateReminder(params[0], Integer.parseInt(params[1])); 
      return "finish"; 
     } 

     @Override 
     protected void onPostExecute(String result) 
     { 
      super.onPostExecute(result); 
      loadSettingsData(); 
      displayView(); 
     } 
    } 
} 

public class SettingsAdapter extends ArrayAdapter<Reminder> 
{ 
    protected static final String TAG = "SettingsAdapter"; 
    private static final int TIME_PICKER_DIALOG = 1; 
    private List<Reminder> arrayListReminders; 
    private int layout; 
    private Activity activity; 

    public SettingsAdapter(Activity activity, int layout, List<Reminder> objects) 
    { 
     super(activity, layout, objects); 

     this.arrayListReminders = objects; 
     this.layout = layout; 
     this.activity = activity; 
    } 

    static class ViewHolder 
    { 
     private TextView listReminderTextView; 
     private Button listReminderTimeButton; 
     private CheckBox listReminderCheckBox; 
    } 

    @Override 
    public View getView(int position, View convertView, android.view.ViewGroup parent) 
    { 
     final Reminder rem = arrayListReminders.get(position); 
     View view = convertView; 
     ViewHolder viewHolder = null; 

     if (view == null) 
     { 
      LayoutInflater layoutInflater = (LayoutInflater) getContext() 
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      view = layoutInflater.inflate(layout, parent, false); 
     } 

     if (view != null) 
     { 
      viewHolder = new ViewHolder(); 
      viewHolder.listReminderTextView = (TextView) view. 
             findViewById(R.id.list_reminder_day_textview); 

      viewHolder.listReminderTimeButton = (Button) view 
           .findViewById(R.id.settings_reminder_list_time_button); 

      viewHolder.listReminderCheckBox = (CheckBox) view 
           .findViewById(R.id.settings_reminder_list_checkbox); 

      switch (rem.getId()) 
      { 
       case 1: 
        viewHolder.listReminderTextView.setText(R.string.Mo); 
        break; 
       case 2: 
        viewHolder.listReminderTextView.setText(R.string.Di); 
        break; 
       case 3: 
        viewHolder.listReminderTextView.setText(R.string.Mi); 
        break; 
       case 4: 
        viewHolder.listReminderTextView.setText(R.string.Do); 
        break; 
       case 5: 
        viewHolder.listReminderTextView.setText(R.string.Fr); 
        break; 
       case 6: 
        viewHolder.listReminderTextView.setText(R.string.Sa); 
        break; 
       case 7: 
        viewHolder.listReminderTextView.setText(R.string.So); 
        break; 
       default: 
        break; 
      } 

      viewHolder.listReminderTimeButton.setText(rem.getTime() + " " + "Uhr"); 

      viewHolder.listReminderTimeButton 
         .setOnClickListener(new OnClickListener() 
         { 
          @Override 
          public void onClick(View v) 
          { 
           Log.i(TAG, "clicked " + rem.toString()); 

           Bundle bundle = new Bundle(); 
           bundle.putSerializable("reminder", rem); 

           ((SettingsActivity) activity).showDialog(TIME_PICKER_DIALOG, bundle); 
          } 
         }); 

      viewHolder.listReminderCheckBox.setChecked(rem.isEnabled() ? true : false); 
     } 
     return view; 
    }; 
} 

感谢您的帮助 - 我改变了getView方法,并开始调试的一切。

我认为问题是在活动中创建TimePicker对话框。

private Dialog showTimePicker(final Bundle b) 
{ 
    TimePickerDialog timePicker = new TimePickerDialog(this, 0, 
         new TimePickerDialog.OnTimeSetListener() 
         { 
          @Override 
          public void onTimeSet(TimePicker view, int hourOfDay,int minute) 
          { 
           mCalendar.set(Calendar.HOUR_OF_DAY, hourOfDay); 
           mCalendar.set(Calendar.MINUTE, minute); 

           Reminder rem = (Reminder) b.get("reminder"); 
           Log.i(TAG, rem.toString() + " got from adapter"); 

           SimpleDateFormat dateFormat = new SimpleDateFormat(TIME_FORMAT); 
           String dateForTimeButton = dateFormat.format(mCalendar.getTime()); 

           rem.setTime(dateForTimeButton); 
           Log.i(TAG, rem.toString()); 
           new UpdateTimerByBtn().execute(new String[] { 
              rem.getTime(), 
              new String(Integer.toString(rem.getId())) 
             }); 
          } 
         }, mCalendar.get(Calendar.HOUR_OF_DAY) 
         , mCalendar.get(Calendar.MINUTE), true); 
    return timePicker; 
} 

我从Bundle中获取所需的对象。这个Bunlde是最终的,当我将一个新的Bundle从适配器传输到活动时,Bunlde永远不会改变。当我点击另一个Button时,会显示相同的对话框(具有相同的值),并且使用该最终捆绑包执行OnTimeSetListener。有没有办法处理dialiogs表单适配器?我应该为ViewHolder中的每一行创建一个对话框吗?

回答

1

在SettingsAdapter类中,getView方法的声音听起来有点不对。首先,你使用ViewHolder模式是错误的。 ViewHolder模式的要点是避免每次使用循环视图时调用findViewById。

当convertView为null时,您需要实例化一个新视图,这就是您要做的。问题是,在这种情况下,你并没有给出它的子视图的任何值......你只是简单地返回视图。

使用ViewHolder模式的典型getView看起来是这样的:

public View getView(int position, View convertView, 
    android.view.ViewGroup parent) { 
    View view = convertView; 
    ViewHolder viewHolder; 

    if(view == null) { 
    view = layoutInflater.inflate ... // instantiate new view here 

    // note that i'm instantiating my View holder when view == null, 
    // where you are instantiating it when view != null... 
    viewHolder = new ViewHolder(); 
    viewHolder.subview1 = (TextView)view.findViewById(R.id.subview1); 
    ... 
    viewHolder.subviewN = (CheckBox)view.findViewById(R.id.subviewN); 
    view.setTag(viewHolder); 
    } 

    viewHolder = (ViewHolder)view.getTag(); 

    // view and viewHolder are now appropriately set, so do with them what you must 

    viewHolder.subview1.setText("blah blah"); 
    ... 

    return view; 
} 

正如我以前说过,你的观点的TextView的,按钮分配值,和CheckBox只有convertView不为空...换句话说,当你创建一个新的视图时,你只需按原样返回它。也许这将是一个开始调试的好地方。

相关问题