制作 ListView 时遇到问题,其中每个项目都显示模型的 ArrayList
Posted
技术标签:
【中文标题】制作 ListView 时遇到问题,其中每个项目都显示模型的 ArrayList【英文标题】:Trouble making a ListView where each item displays an ArrayList of a model 【发布时间】:2015-08-01 15:23:04 【问题描述】:我正在处理警报我已经设置了整个警报系统(模型、数据库、服务、接收器等),但这不是重点。
我将每个警报分组到一个名为“matchingAlarms”的数组列表中,该数组列表基于用户输入的重复天数(周日至周六)。 我把这部分记下来了,没问题
现在使用 matchAlarms Arraylist,我正在尝试创建一个 ListView,其中 ListView 中的每个项目都显示该 arraylist 的每个索引的警报名称和警报时间(我希望它们在 ListView 中使用计时器进行更改)。
例子:
我有 1 个闹钟:上午 8 点 - 晚上 11 点,重复天数:周日至周四 AND 1 个闹钟,上午 9 点至下午 12 点,重复天数:周五至周六
这些警报中的每一个都在matchingAlarms Arraylist的索引中, 所以matchingAlarms的大小是2。
我想我提到了所有内容,现在是代码。
AlarmListAdapter:
public class AlarmListAdapter extends BaseAdapter
public static Context mContext;
private List<AlarmModel> mAlarms;
private ArrayList<ArrayList<AlarmModel>> mMatchingAlarms = new ArrayList<ArrayList<AlarmModel>>();
private ArrayList<AlarmModel> grouped = new ArrayList<AlarmModel>();
private Animation anim;
AlarmModel model;
TextView txtTime,txtName,sun,mon,tue,wed,thur,fri,sat;
ToggleButton btnToggle;
int matchingAlarmsIndex = 0;
int groupIndex = 0;
int itemIndex;
public AlarmListAdapter(Context context, List<AlarmModel> alarms, ArrayList<ArrayList<AlarmModel>> matchingAlarms)
mContext = context;
mAlarms = alarms;
mMatchingAlarms = matchingAlarms;
anim = AnimationUtils.loadAnimation(mContext, R.anim.right_left);
public AlarmListAdapter(Context context)
mContext = context;
public void setAlarms(List<AlarmModel> alarms)
mAlarms = alarms;
@Override
public int getCount()
if (mMatchingAlarms != null)
return mMatchingAlarms.size();
return 0;
@Override
public ArrayList<AlarmModel> getItem(int position)
if (mMatchingAlarms != null)
return mMatchingAlarms.get(position);
return null;
@Override
public long getItemId(int position)
if (mAlarms != null)
return mAlarms.get(position).id;
return 0;
@Override
public View getView(int position, View view, ViewGroup parent)
if (view == null)
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.alarm_list_item, parent, false);
txtName = (TextView) view.findViewById(R.id.alarm_item_name);
txtTime = (TextView) view.findViewById(R.id.alarm_item_time);
sun = (TextView) view.findViewById(R.id.alarm_item_sunday);
mon = (TextView) view.findViewById(R.id.alarm_item_monday);
tue = (TextView) view.findViewById(R.id.alarm_item_tuesday);
wed = (TextView) view.findViewById(R.id.alarm_item_wednesday);
thur = (TextView) view.findViewById(R.id.alarm_item_thursday);
fri = (TextView) view.findViewById(R.id.alarm_item_friday);
sat = (TextView) view.findViewById(R.id.alarm_item_saturday);
btnToggle = (ToggleButton) view.findViewById(R.id.alarm_item_toggle);
grouped = getItem(position);
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask()
public void run()
((AlarmListActivity) mContext).runOnUiThread(new Runnable()
@Override
public void run()
if ((groupIndex + 1) <= grouped.size())
model = grouped.get(groupIndex);
updateTimeAndDates(model);
groupIndex++;
if ((groupIndex + 1) > grouped.size())
groupIndex = 0;
Log.i("", String.valueOf(groupIndex));
);
, 0, 2500);
return view;
private void updateTextColor(TextView view, boolean isOn)
if (isOn)
view.setTextColor(Colors.IndianRed);
else
view.setTextColor(Color.LTGRAY);
private void updateTimeAndDates(AlarmModel model)
txtName.setText(model.name);
txtName.startAnimation(anim);
txtTime.setText(DietDoctor.to12Hours(model.timeHour, model.timeMinute));
txtTime.startAnimation(anim);
updateTextColor(sun, model.getRepeatingDay(AlarmModel.SUNDAY));
updateTextColor(mon, model.getRepeatingDay(AlarmModel.MONDAY));
updateTextColor(tue, model.getRepeatingDay(AlarmModel.TUESDAY));
updateTextColor(wed, model.getRepeatingDay(AlarmModel.WEDNESDAY));
updateTextColor(thur, model.getRepeatingDay(AlarmModel.THURSDAY));
updateTextColor(fri, model.getRepeatingDay(AlarmModel.FRDIAY));
updateTextColor(sat, model.getRepeatingDay(AlarmModel.SATURDAY));
btnToggle.setChecked(model.isEnabled);
AlarmListActivity:
public class AlarmListActivity extends ListActivity
private AlarmListAdapter mAdapter;
private AlarmDBHelper dbHelper = new AlarmDBHelper(this);
private Context mContext;
private boolean fromSettings;
private ArrayList<ArrayList<AlarmModel>> matchingAlarms = new ArrayList<ArrayList<AlarmModel>>();
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
if(getIntent().hasExtra("FromSettings"))
fromSettings = getIntent().getExtras().getBoolean("FromSettings");
mContext = this;
requestWindowFeature(Window.FEATURE_ACTION_BAR);
setContentView(R.layout.activity_alarmlist);
setGroups();
mAdapter = new AlarmListAdapter(this, dbHelper.getAlarms(), matchingAlarms);
setListAdapter(mAdapter);
...
public void setGroups()
ArrayList<AlarmModel> group = new ArrayList<AlarmModel>();
List<AlarmModel> mAlarms = dbHelper.getAlarms();
for (int i = 0; i < mAlarms.size(); i++)
if ((i + 1) != mAlarms.size())
boolean result = Arrays.equals(mAlarms.get(i).getRepeatingDays(), mAlarms.get(i + 1).getRepeatingDays());
Log.i("Result", Boolean.toString(result));
if (result)
if (i == 0)group.add(mAlarms.get(i));
group.add(mAlarms.get(i+1));
if (!result)
if (i == 0)group.add(mAlarms.get(i));
matchingAlarms.add(group);
group = new ArrayList<AlarmModel>();
group.add(mAlarms.get(i+1));
if ((i + 1) == mAlarms.size())
boolean result1 = Arrays.equals(mAlarms.get(i).getRepeatingDays(), mAlarms.get(i - 1).getRepeatingDays());
Log.i("Result_1", Boolean.toString(result1));
if (result1)
group.add(mAlarms.get(i));
matchingAlarms.add(group);
if (!result1)
matchingAlarms.add(group);
group = new ArrayList<AlarmModel>();
group.add(mAlarms.get(i));
Log.i("Matching Alarms", String.valueOf(matchingAlarms.size()));
Log.i("Group", String.valueOf(matchingAlarms.get(0).size()));
Log.i("UnGrouped", String.valueOf(mAlarms.size()));
我认为真正的问题在于 getView 方法和其中的计时器。 正如你从下面的图片中看到的,我只有周五到周六去。第一项应该有重复日期的警报:Sun-Thurs
【问题讨论】:
【参考方案1】:这是因为getView
被多次调用(ListView
上的每个项目至少调用一次)。
因此,在您的适配器上,当您使用所有这些 TextView
字段时,您每次都会覆盖它们的引用,并且只有最后一个是真正正确的。
要解决这个问题,最好的办法是应用Holder
模式。如果你用谷歌搜索它,你会发现大约一百万五十万个例子以及它是如何工作的。
private static class Holder
AlarmModel model;
TextView txtTime,txtName,sun,mon,tue,wed,thur,fri,sat;
ToggleButton btnToggle;
Timer timer = new Timer();
然后将您的updateTimeAndDates
更新为:
updateTimeAndDates(Holder h)
h.timer.cancel();
h.timer.purge();
// carry on updating the values and create the re-schedule the updates.
我也建议不要使用计时器,只需在视图上使用.postDealayed(Runnable, long);
。计时器根本不是做得很好的课程。
【讨论】:
以上是关于制作 ListView 时遇到问题,其中每个项目都显示模型的 ArrayList的主要内容,如果未能解决你的问题,请参考以下文章
片段中 ListView 的 setOnItemClickListener
每个项目中带有 Switch 和 TextView 的自定义 ListView
如何使用 firebase 获取 listView 中每个项目的数据?
使用 CardView BaseAdapter OnItemClick 自定义 ListView