我有ViewPager
个标签。在每个中都有一个RecyclerView
。每个RecyclerView
都有自己的Adapter
。我有一个名为GlobalData
的单例类,在该类中,我有3个ArrayLists
包含每个Adapter
的数据。更具体地说,第一个标签显示个月,第二个标签显示周,第三个标签显示天。只能天才能更改,添加或删除。 周和月应相应调整。
一天 代表工作日。我已经实施了添加,删除和更改天的逻辑以及用于调整周和月的逻辑。但我需要一种非常有效的方式来通知Adapters
数据已被更改,删除或修改。
我可以在滚动到notifyDataSetChanged()
标签时调用每个适配器的ViewPager
来实现此目的。
tabStrip.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
switch (position) {
case WorkingFragmentAdapter.DAYS_PAGE:
daysAdapter.notifyDataSetChanged();
break;
case WorkingFragmentAdapter.WEEKS_PAGE:
weeksAdapter.notifyDataSetChanged();
break;
case WorkingFragmentAdapter.MONTHS_PAGE:
monthsAdapter.notifyDataSetChanged();
break;
}
}
但是当RecyclerView
中显示大量数据并且应用程序的性能较低时,这样的代码非常耗时。
我正在考虑一种方法,我会记住天,周和月的每个修改,添加和删除位置的位置,以及滚动到页面时,请通知Adapter
。
我遇到的第二种方法是在Adapter
中存储每个GlobalData
的引用,并从GlobalData
通知每个适配器。
你能告诉我还是暗示我最好的解决办法是什么?提前谢谢。
答案 0 :(得分:0)
我刚刚经历过这样的事情,其中用户操作可能会影响多达六个不同的片段以及它们各自的适配器。当用户与UI交互时,他们会轻扫视图寻呼机,并以随机方式创建/销毁片段。
在开始创建大量错误的设计之后,我重写了代码以获得正确的设计。让我分享一下我学到的东西:
首先要有一个专门用于UI模型的类。在您的情况下,您班级的实例将包含月份列表,周列表和天数列表。它还会包含当前选定的月/周/日以及捕获UI当前状态的任何其他数据。
我不推荐全局数据单例。相反,让Activity持有对模型对象的引用。当片段在onCreate()
中时,调用getActivity()
以查找模型对象的交换所很容易。这有一个很好的理由:您的模型需要在配置更改时保留并重新创建。
因此,为此,您的模型类应该实现Parcelable
并具有保存和恢复其状态所需的所有逻辑。然后覆盖活动的onSaveInstanceState()
方法,以使用Bundle.putParcelable()
保存模型。当活动在onCreate()
时,检查保存的实例状态并在必要时恢复模型。
对于适配器,您的模型类应提供获取数据的方法,例如getMonthList()
,getWeekList()
,getSelectedWeek()
,getSelectedDay()
等。 。片段将在onCreateView()
中调用这些方法来设置其适配器并以正确的状态显示UI。 重要提示:任何返回集合的方法,例如月/周/等的列表。应该返回一个不可变的数组,而不仅仅是对模型中列表的引用。您希望客户端对列表具有完全独立的引用,否则会出现副作用,因为模型的更改会立即影响适配器 并导致RecyclerView
崩溃,因为{{1}没有被叫过。这条建议可能会让你节省大约一周的挫折感。
您的模型类将是UI事件的接收器和发送器。在接收方:您将定义一些方法,如notifyDataSetChanged()
,selectWeek(week)
等,以告知您的模型用户刚才所做的事情。该方法将使数据发生变化,然后通知所有听众,接下来将对此进行讨论。
在发送方:您的模型类应该至少定义一个接口 - 我称之为selectDay(day)
- 它将定义模型可以更改的所有方式的回调方法。一些示例:CalendarUIListener
,onWeekSelected(week)
,onDaySelected(day)
等。您的模型还需要通过两种方法onMonthListChanged(List<month>)
和addListener()
维护一个侦听器列表。
您的视图寻呼机片段可以实现此接口以接收事件通知。这些视图寻呼机片段应调用removeListener()
中的model.addListener(this)
和onCreate()
中的model.removeListener(this)
。或者,片段可以创建匿名侦听器对象并注册/取消注册,而不是直接实现接口。
现在,您的听众可以接收事件并做出相应的回应。假设您的用户选择了一个更改日期列表的周(假设您有一个onDestroy()
类和一个自定义适配器)。您的代码可能如下所示:
Day
这是本土事件总线的一个例子。您还可以使用事件总线库使所有接线更容易(即在正确的位置呼叫 @Override
public void onDayListChanged(Day[] days) {
if (mAdapter != null) {
mAdapter.setDays(days); // this method would call notifyDataSetChanged()
}
}
&amp; addListener()
)。我的特定应用程序还有一些额外的挑战,例如每当UI事件发生时从服务器检索数据,然后在请求完成时广播该数据事件。使用这种架构可以更容易地找出哪个类负责什么操作。
最后一件事:我确实遇到了配置发生变化的鸡/蛋问题,其中片段显然是在活动的removeListener()
中重新创建的,这使我没有机会从保存的实例状态恢复模型活动。我编写了一个抽象基类,为我的片段实现了监听器,所以我的代码看起来像这样:
super.onCreate()