ViewModel 未在 Fragment 的第一个 onCreateView 上检索数据
ViewModel not retrieving data on Fragment´s first onCreateView
我正在尝试从我的 SQLite 数据库中检索警报列表。当我第一次进入 Fragment 时,列表未检索,但如果我退出 Fragment 并再次输入,它确实会正确检索。
片段是包含 3 个片段的 Activity(主Activity)的一部分。用户可以通过单击选项卡 (TabLayout) 在 Fragment 之间移动。
第一个片段使用相同的方法来检索列表。第一个片段用于创建警报列表。
创建的警报将在选定的工作日(所有星期一、星期二等)重复,然后是第二个,最后是第三个片段。最后一个用于显示 CalendarView
上的警报
如何让它在第三个片段中第一次尝试检索数据?
public class TabFragmentCalendar extends Fragment {
private View view;
private List<EventDay> events = new ArrayList<>();
private com.applandeo.materialcalendarview.CalendarView calendarView;
private MyViewModel myViewModel;
private ArrayList<Alarm> listAlarms = new ArrayList<>();
private ExecutorService executorService;
public TabFragmentCalendario() {}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_tab_calendar, container, false);
myViewModel = new ViewModelProvider(this).get(MyViewModel.class);
myViewModel.getAllAlarms().observe(getViewLifecycleOwner(), new Observer<List<Alarm>>() {
@Override
public void onChanged(List<Alarm> alarms) {
listAlarms = (ArrayList<Alarm>) alarms;
}
});
for(Alarm alarm : listAlarms){
Log.d("FragmentCalendar", "Alarm = " + alarm.getHour() + ":" + alarm.getMinute());
} // To check if the alarms are retrieved
calendarView = view.findViewById(R.id.calendarView);
executorService = Executors.newSingleThreadExecutor();
executorService.execute(new DisplayEvents(calendarView, events, listAlarms));
return view;
}
@Override
public void onDestroy() {
super.onDestroy();
//popularCalendario.interrupt();
executorService.shutdown();
}
如您所见,我创建了一个新线程以在 CalendarView 中显示警报。
创建闹钟以在选定的工作日(所有星期一)重复。
这是该线程的代码。
public class DisplayEvents implements Runnable {
private final List<EventDay> events;
private final CalendarView calendarView;
private final ArrayList<Alarm> listAlarms;
public DisplayEventos(CalendarView calendarView, List<EventDay> events, ArrayList<Alarm> listAlarms) {
this.calendarView = calendarView;
this.events = events;
this.listAlarms = listAlarms;
}
@Override
public void run() {
for (Alarm alarm : listAlarms) {
for (int j = 0; j < 12; j++) {
if (alarma.getMonday()) {
for (int i = 1; i <= 5; i++) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.MONTH, j);
calendar.set(Calendar.DAY_OF_WEEK, 2);
calendar.set(Calendar.WEEK_OF_MONTH, i);
events.add(new EventDay(calendar, R.drawable.ic_alarm));
}
}
if (alarm.getTuesday()) {
for (int i = 1; i <= 5; i++) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.MONTH, j);
calendar.set(Calendar.DAY_OF_WEEK, 3);
calendar.set(Calendar.WEEK_OF_MONTH, i);
events.add(new EventDay(calendar, R.drawable.ic_alarm));
}
}
if (alarma.getWednesday()) {
for (int i = 1; i <= 5; i++) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.MONTH, j);
calendar.set(Calendar.DAY_OF_WEEK, 4);
calendar.set(Calendar.WEEK_OF_MONTH, i);
events.add(new EventDay(calendar, R.drawable.ic_alarm));
}
}
if (alarma.getThursday()) {
for (int i = 1; i <= 5; i++) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.MONTH, j);
calendar.set(Calendar.DAY_OF_WEEK, 5);
calendar.set(Calendar.WEEK_OF_MONTH, i);
events.add(new EventDay(calendar, R.drawable.ic_alarm));
}
}
if (alarma.getFriday()) {
for (int i = 1; i <= 5; i++) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.MONTH, j);
calendar.set(Calendar.DAY_OF_WEEK, 6);
calendar.set(Calendar.WEEK_OF_MONTH, i);
events.add(new EventDay(calendar, R.drawable.ic_alarm));
}
}
if (alarma.getSaturday()) {
for (int i = 1; i <= 5; i++) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.MONTH, j);
calendar.set(Calendar.DAY_OF_WEEK, 7);
calendar.set(Calendar.WEEK_OF_MONTH, i);
events.add(new EventDay(calendar, R.drawable.ic_alarm));
}
}
if (alarma.getSunday()) {
for (int i = 1; i <= 5; i++) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.MONTH, j);
calendar.set(Calendar.DAY_OF_WEEK, 1);
calendar.set(Calendar.WEEK_OF_MONTH, i);
events.add(new EventDay(calendar, R.drawable.ic_alarm));
}
}
}
}
calendarView.post(new Runnable() {
@Override
public void run() {
calendarView.setEvents(events);
}
});
}
}
Android Studio 表示:
I/Choreographer: Skipped 89 frames! The application may be doing too much work on its main thread.
我是这个世界的新手,我知道我犯了很多错误。欢迎任何建议:)
当你打电话时
myViewModel.getAllAlarms().observe(getViewLifecycleOwner(), new Observer<List<Alarm>>() {
@Override
public void onChanged(List<Alarm> alarms) {
listAlarms = (ArrayList<Alarm>) alarms;
}
});
特别是 myViewModel.getAllAlarms()
,它 return 是您正在观察的 return 东西,但它不会 return 数据 立即。您唯一可以访问该数据的地方是 onChanged
@Override
public void onChanged(List<Alarm> alarms) {
//here, we actually do have data, so do whatever you want here (probably should do a null check, just in case)
executorService.execute(new DisplayEvents(calendarView, events, listAlarms));
}
所以当你打电话时 :
executorService.execute(new DisplayEvents(calendarView, events, listAlarms));
您的列表还没有数据。
像这样更改您的 onCreateView 方法
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_tab_calendar, container, false);
calendarView = view.findViewById(R.id.calendarView);
executorService = Executors.newSingleThreadExecutor();
myViewModel = new ViewModelProvider(this).get(MyViewModel.class);
myViewModel.getAllAlarms().observe(getViewLifecycleOwner(), new Observer<List<Alarm>>() {
@Override
public void onChanged(List<Alarm> alarms) {
listAlarms = (ArrayList<Alarm>) alarms;
executorService.execute(new DisplayEvents(calendarView, events, listAlarms));
}
});
for(Alarm alarm : listAlarms){
Log.d("FragmentCalendar", "Alarm = " + alarm.getHour() + ":" + alarm.getMinute());
} // To check if the alarms are retrieved
return view;
}
因为在你的代码中 executorService.execute(new DisplayEvents(calendarView, events, listAlarms));在 onChanged 方法之前被调用 return 报警列表
我正在尝试从我的 SQLite 数据库中检索警报列表。当我第一次进入 Fragment 时,列表未检索,但如果我退出 Fragment 并再次输入,它确实会正确检索。
片段是包含 3 个片段的 Activity(主Activity)的一部分。用户可以通过单击选项卡 (TabLayout) 在 Fragment 之间移动。 第一个片段使用相同的方法来检索列表。第一个片段用于创建警报列表。 创建的警报将在选定的工作日(所有星期一、星期二等)重复,然后是第二个,最后是第三个片段。最后一个用于显示 CalendarView
上的警报如何让它在第三个片段中第一次尝试检索数据?
public class TabFragmentCalendar extends Fragment {
private View view;
private List<EventDay> events = new ArrayList<>();
private com.applandeo.materialcalendarview.CalendarView calendarView;
private MyViewModel myViewModel;
private ArrayList<Alarm> listAlarms = new ArrayList<>();
private ExecutorService executorService;
public TabFragmentCalendario() {}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_tab_calendar, container, false);
myViewModel = new ViewModelProvider(this).get(MyViewModel.class);
myViewModel.getAllAlarms().observe(getViewLifecycleOwner(), new Observer<List<Alarm>>() {
@Override
public void onChanged(List<Alarm> alarms) {
listAlarms = (ArrayList<Alarm>) alarms;
}
});
for(Alarm alarm : listAlarms){
Log.d("FragmentCalendar", "Alarm = " + alarm.getHour() + ":" + alarm.getMinute());
} // To check if the alarms are retrieved
calendarView = view.findViewById(R.id.calendarView);
executorService = Executors.newSingleThreadExecutor();
executorService.execute(new DisplayEvents(calendarView, events, listAlarms));
return view;
}
@Override
public void onDestroy() {
super.onDestroy();
//popularCalendario.interrupt();
executorService.shutdown();
}
如您所见,我创建了一个新线程以在 CalendarView 中显示警报。 创建闹钟以在选定的工作日(所有星期一)重复。
这是该线程的代码。
public class DisplayEvents implements Runnable {
private final List<EventDay> events;
private final CalendarView calendarView;
private final ArrayList<Alarm> listAlarms;
public DisplayEventos(CalendarView calendarView, List<EventDay> events, ArrayList<Alarm> listAlarms) {
this.calendarView = calendarView;
this.events = events;
this.listAlarms = listAlarms;
}
@Override
public void run() {
for (Alarm alarm : listAlarms) {
for (int j = 0; j < 12; j++) {
if (alarma.getMonday()) {
for (int i = 1; i <= 5; i++) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.MONTH, j);
calendar.set(Calendar.DAY_OF_WEEK, 2);
calendar.set(Calendar.WEEK_OF_MONTH, i);
events.add(new EventDay(calendar, R.drawable.ic_alarm));
}
}
if (alarm.getTuesday()) {
for (int i = 1; i <= 5; i++) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.MONTH, j);
calendar.set(Calendar.DAY_OF_WEEK, 3);
calendar.set(Calendar.WEEK_OF_MONTH, i);
events.add(new EventDay(calendar, R.drawable.ic_alarm));
}
}
if (alarma.getWednesday()) {
for (int i = 1; i <= 5; i++) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.MONTH, j);
calendar.set(Calendar.DAY_OF_WEEK, 4);
calendar.set(Calendar.WEEK_OF_MONTH, i);
events.add(new EventDay(calendar, R.drawable.ic_alarm));
}
}
if (alarma.getThursday()) {
for (int i = 1; i <= 5; i++) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.MONTH, j);
calendar.set(Calendar.DAY_OF_WEEK, 5);
calendar.set(Calendar.WEEK_OF_MONTH, i);
events.add(new EventDay(calendar, R.drawable.ic_alarm));
}
}
if (alarma.getFriday()) {
for (int i = 1; i <= 5; i++) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.MONTH, j);
calendar.set(Calendar.DAY_OF_WEEK, 6);
calendar.set(Calendar.WEEK_OF_MONTH, i);
events.add(new EventDay(calendar, R.drawable.ic_alarm));
}
}
if (alarma.getSaturday()) {
for (int i = 1; i <= 5; i++) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.MONTH, j);
calendar.set(Calendar.DAY_OF_WEEK, 7);
calendar.set(Calendar.WEEK_OF_MONTH, i);
events.add(new EventDay(calendar, R.drawable.ic_alarm));
}
}
if (alarma.getSunday()) {
for (int i = 1; i <= 5; i++) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.MONTH, j);
calendar.set(Calendar.DAY_OF_WEEK, 1);
calendar.set(Calendar.WEEK_OF_MONTH, i);
events.add(new EventDay(calendar, R.drawable.ic_alarm));
}
}
}
}
calendarView.post(new Runnable() {
@Override
public void run() {
calendarView.setEvents(events);
}
});
}
}
Android Studio 表示:
I/Choreographer: Skipped 89 frames! The application may be doing too much work on its main thread.
我是这个世界的新手,我知道我犯了很多错误。欢迎任何建议:)
当你打电话时
myViewModel.getAllAlarms().observe(getViewLifecycleOwner(), new Observer<List<Alarm>>() {
@Override
public void onChanged(List<Alarm> alarms) {
listAlarms = (ArrayList<Alarm>) alarms;
}
});
特别是 myViewModel.getAllAlarms()
,它 return 是您正在观察的 return 东西,但它不会 return 数据 立即。您唯一可以访问该数据的地方是 onChanged
@Override
public void onChanged(List<Alarm> alarms) {
//here, we actually do have data, so do whatever you want here (probably should do a null check, just in case)
executorService.execute(new DisplayEvents(calendarView, events, listAlarms));
}
所以当你打电话时 :
executorService.execute(new DisplayEvents(calendarView, events, listAlarms));
您的列表还没有数据。
像这样更改您的 onCreateView 方法
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.fragment_tab_calendar, container, false);
calendarView = view.findViewById(R.id.calendarView);
executorService = Executors.newSingleThreadExecutor();
myViewModel = new ViewModelProvider(this).get(MyViewModel.class);
myViewModel.getAllAlarms().observe(getViewLifecycleOwner(), new Observer<List<Alarm>>() {
@Override
public void onChanged(List<Alarm> alarms) {
listAlarms = (ArrayList<Alarm>) alarms;
executorService.execute(new DisplayEvents(calendarView, events, listAlarms));
}
});
for(Alarm alarm : listAlarms){
Log.d("FragmentCalendar", "Alarm = " + alarm.getHour() + ":" + alarm.getMinute());
} // To check if the alarms are retrieved
return view;
}
因为在你的代码中 executorService.execute(new DisplayEvents(calendarView, events, listAlarms));在 onChanged 方法之前被调用 return 报警列表