aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Patterson <jdp@google.com>2020-08-28 13:51:40 +0200
committerJohn Patterson <jdp@google.com>2020-10-12 09:05:13 +0000
commit9c08312784ae07634761ea3be402d6478a57e385 (patch)
treef6f4d0c386a364b93620b78dc8344d2b31a1f3b8 /src
parent1de3c508609b7e725b53af825f2c96b1eaa47d80 (diff)
downloadCalendar-9c08312784ae07634761ea3be402d6478a57e385.tar.gz
Do not set an initial value for events.
This avoids the empty events being used to show "no events" message. Fixes: 153622413 Test: atest CarCalendarUnitTests CarCalendarUiTests Change-Id: Ib02ba2d8682bd92a560b73b0db4702ec4ac45e73
Diffstat (limited to 'src')
-rw-r--r--src/com/android/car/calendar/CarCalendarView.java39
-rw-r--r--src/com/android/car/calendar/common/EventsLiveData.java22
2 files changed, 35 insertions, 26 deletions
diff --git a/src/com/android/car/calendar/CarCalendarView.java b/src/com/android/car/calendar/CarCalendarView.java
index 07b9516..1a63588 100644
--- a/src/com/android/car/calendar/CarCalendarView.java
+++ b/src/com/android/car/calendar/CarCalendarView.java
@@ -17,7 +17,6 @@
package com.android.car.calendar;
import static com.google.common.base.Verify.verify;
-import static com.google.common.base.Verify.verifyNotNull;
import android.Manifest;
import android.util.Log;
@@ -25,10 +24,10 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
-import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.Observer;
import androidx.recyclerview.widget.RecyclerView;
+import androidx.recyclerview.widget.RecyclerView.ViewHolder;
import com.android.car.calendar.common.CalendarFormatter;
import com.android.car.calendar.common.Dialer;
@@ -64,15 +63,8 @@ class CarCalendarView {
/** Holds an instance of either {@link LocalDate} or {@link Event} for each item in the list. */
private final List<CalendarItem> mRecyclerViewItems = new ArrayList<>();
- private final RecyclerView.Adapter mAdapter = new EventRecyclerViewAdapter();
- private final Observer<ImmutableList<Event>> mEventsObserver =
- events -> {
- if (DEBUG) Log.d(TAG, "Events changed");
- updateRecyclerViewItems(events);
-
- // TODO(jdp) Only change the affected items (DiffUtil) to allow animated changes.
- mAdapter.notifyDataSetChanged();
- };
+ private final RecyclerView.Adapter<ViewHolder> mAdapter = new EventRecyclerViewAdapter();
+ private final Observer<ImmutableList<Event>> mEventsObserver = this::onEventsChanged;
CarCalendarView(
CarCalendarActivity carCalendarActivity,
@@ -102,23 +94,30 @@ class CarCalendarView {
private void showWithPermission() {
EventsLiveData eventsLiveData = mCarCalendarViewModel.getEventsLiveData();
eventsLiveData.observe(mCarCalendarActivity, mEventsObserver);
- updateRecyclerViewItems(verifyNotNull(eventsLiveData.getValue()));
+ }
+
+ private void onEventsChanged(ImmutableList<Event> events) {
+ updateRecyclerViewItems(events);
+
+ // TODO(jdp) Only change the affected items (DiffUtil) to allow animated changes.
+ mAdapter.notifyDataSetChanged();
}
/**
* If the events list is null there is no calendar data available. If the events list is empty
* there is calendar data but no events.
*/
- private void updateRecyclerViewItems(@Nullable ImmutableList<Event> carCalendarEvents) {
+ private void updateRecyclerViewItems(@Nullable ImmutableList<Event> events) {
+ if (DEBUG) Log.d(TAG, "Update events");
LocalDate currentDate = null;
mRecyclerViewItems.clear();
- if (carCalendarEvents == null) {
+ if (events == null) {
mNoEventsTextView.setVisibility(View.VISIBLE);
mNoEventsTextView.setText(R.string.no_calendars);
return;
}
- if (carCalendarEvents.isEmpty()) {
+ if (events.isEmpty()) {
mNoEventsTextView.setVisibility(View.VISIBLE);
mNoEventsTextView.setText(R.string.no_events);
return;
@@ -130,7 +129,7 @@ class CarCalendarView {
// add the event rows after looking at all events for the day.
List<CalendarItem> eventItems = null;
List<EventCalendarItem> allDayEventItems = null;
- for (Event event : carCalendarEvents) {
+ for (Event event : events) {
LocalDate date =
event.getDayStartInstant().atZone(ZoneId.systemDefault()).toLocalDate();
@@ -177,17 +176,15 @@ class CarCalendarView {
mRecyclerViewItems.addAll(eventItems);
}
- private class EventRecyclerViewAdapter extends RecyclerView.Adapter {
-
- @NonNull
+ private class EventRecyclerViewAdapter extends RecyclerView.Adapter<ViewHolder> {
@Override
- public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
CalendarItem.Type type = CalendarItem.Type.values()[viewType];
return type.createViewHolder(parent);
}
@Override
- public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
+ public void onBindViewHolder(ViewHolder holder, int position) {
mRecyclerViewItems.get(position).bind(holder);
}
diff --git a/src/com/android/car/calendar/common/EventsLiveData.java b/src/com/android/car/calendar/common/EventsLiveData.java
index f2df3fe..92ae0bb 100644
--- a/src/com/android/car/calendar/common/EventsLiveData.java
+++ b/src/com/android/car/calendar/common/EventsLiveData.java
@@ -31,7 +31,9 @@ import android.provider.CalendarContract;
import android.provider.CalendarContract.Instances;
import android.util.Log;
+import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LiveData;
+import androidx.lifecycle.Observer;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
@@ -54,6 +56,8 @@ import javax.annotation.Nullable;
* Provider</a>.
*
* <p>While in the active state the content provider is observed for changes.
+ *
+ * <p>When the value given to the observer is null it signals that there are no calendars.
*/
public class EventsLiveData extends LiveData<ImmutableList<Event>> {
@@ -72,20 +76,22 @@ public class EventsLiveData extends LiveData<ImmutableList<Event>> {
private final ContentResolver mContentResolver;
private final EventDescriptions mEventDescriptions;
private final EventLocations mLocations;
- private final Runnable mUpdateRunnable = this::updateIfChanged;
+ private final Runnable mUpdateIfChangedRunnable = this::updateIfChanged;
/** The event instances cursor is a field to allow observers to be managed. */
@Nullable private Cursor mEventsCursor;
@Nullable private ContentObserver mEventInstancesObserver;
+ // This can be updated on the background thread but read from any thread.
+ private volatile boolean mValueUpdated;
+
public EventsLiveData(
Clock clock,
Handler backgroundHandler,
ContentResolver contentResolver,
EventDescriptions eventDescriptions,
EventLocations locations) {
- super(ImmutableList.of());
mClock = clock;
mBackgroundHandler = backgroundHandler;
mContentResolver = contentResolver;
@@ -95,10 +101,14 @@ public class EventsLiveData extends LiveData<ImmutableList<Event>> {
/** Refreshes the event instances and sets the new value which notifies observers. */
private void updateIfChanged() {
+ Log.d(TAG, "Update if changed");
ImmutableList<Event> latest = getEventsUntilTomorrow();
ImmutableList<Event> current = getValue();
- if (!Objects.equals(latest, current)) {
+
+ // Always post the first value even if it is null.
+ if (!mValueUpdated || !Objects.equals(latest, current)) {
postValue(latest);
+ mValueUpdated = true;
}
}
@@ -187,8 +197,9 @@ public class EventsLiveData extends LiveData<ImmutableList<Event>> {
private void updateWithDelay() {
// Do not update the events until there have been no changes for a given duration.
- mBackgroundHandler.removeCallbacks(mUpdateRunnable);
- mBackgroundHandler.postDelayed(mUpdateRunnable, UPDATE_DELAY_MILLIS);
+ Log.d(TAG, "Events changed");
+ mBackgroundHandler.removeCallbacks(mUpdateIfChangedRunnable);
+ mBackgroundHandler.postDelayed(mUpdateIfChangedRunnable, UPDATE_DELAY_MILLIS);
}
/** Can return multiple events for a single cursor row when an event spans multiple days. */
@@ -277,6 +288,7 @@ public class EventsLiveData extends LiveData<ImmutableList<Event>> {
if (DEBUG) Log.d(TAG, "Live data inactive");
mBackgroundHandler.post(this::cancelScheduledUpdate);
mBackgroundHandler.post(this::tearDownCursor);
+ mValueUpdated = false;
}
/** Calls {@link #updateIfChanged()} every minute to keep the displayed time range correct. */