[英]Android AsyncTask with ListView containing Button onClickListener
我有一个用数据表单sqlitedatabase填充的listview。 列表视图元素包含一个TextView,一个Button和一个Checkbox。 单击按钮将显示一个时间选择器对话框。 从timepickerdialog接受时间将启动AsyncTask。 当我单击按钮时,总是会创建一个新的AsyncTask。
现在,当我单击第七个列表项时,第一个列表项已更新。 线程可能有错误。
活动:
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方法并开始调试所有内容。
我认为问题是在“活动”中创建“时间选择器”对话框的位置。
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从适配器转移到Activity时,此Bunlde是最终的,永远不会更改。 当我单击另一个按钮时,将显示相同的对话框(具有相同的值),并使用该最终捆绑包执行OnTimeSetListener。 有没有办法处理Dialiogs表单适配器? 我应该为ViewHolder中的每一行创建一个对话框吗?
听起来好像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;
}
如前所述,仅当convertView不为null时,才为视图的TextView,Button和CheckBox分配值。换句话说,当您创建新的View时,只需按原样返回即可。 也许那将是开始调试的好地方。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.