Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/193.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android AsyncTask,ListView包含按钮onClickListener_Android_Thread Safety_Android Asynctask_Android Listview - Fatal编程技术网

Android AsyncTask,ListView包含按钮onClickListener

Android AsyncTask,ListView包含按钮onClickListener,android,thread-safety,android-asynctask,android-listview,Android,Thread Safety,Android Asynctask,Android Listview,我有一个列表视图,其中填充了数据表单SQLITE数据库。列表视图元素包含文本视图、按钮和复选框。单击该按钮将显示一个时间选择器对话框。从timepickerdialog接受时间将启动异步任务。当我单击按钮时,总会创建一个新的AsyncTask 现在,当我单击第七个列表项时,第一个列表项被更新。线程可能有错误 活动: public class SettingsActivity extends Activity { private static final String TAG = "Se

我有一个列表视图,其中填充了数据表单SQLITE数据库。列表视图元素包含文本视图、按钮和复选框。单击该按钮将显示一个时间选择器对话框。从timepickerdialog接受时间将启动异步任务。当我单击按钮时,总会创建一个新的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;
    };
}

我从Bundle中获取所需的对象。这个Bunlde是最终的,当我将新Bundle从适配器传输到活动时,它不会改变。当我单击另一个按钮时,将显示相同的对话框(具有相同的值),并使用最后一个包执行OnTimeSetListener。有没有办法处理拨号表适配器?是否应该为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赋值。。。换句话说,创建新视图时,只需按原样返回即可。也许这是开始调试的好地方。

听起来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赋值。。。换句话说,创建新视图时,只需按原样返回即可。也许那是开始调试的好地方