summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/widget/DateTimeView.java19
-rw-r--r--core/tests/coretests/src/android/widget/DateTimeViewTest.java45
2 files changed, 61 insertions, 3 deletions
diff --git a/core/java/android/widget/DateTimeView.java b/core/java/android/widget/DateTimeView.java
index 2c6264783f56..41ff69d6fb5f 100644
--- a/core/java/android/widget/DateTimeView.java
+++ b/core/java/android/widget/DateTimeView.java
@@ -32,6 +32,7 @@ import android.content.res.TypedArray;
import android.database.ContentObserver;
import android.os.Build;
import android.os.Handler;
+import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.PluralsMessageFormatter;
import android.view.accessibility.AccessibilityNodeInfo;
@@ -230,7 +231,7 @@ public class DateTimeView extends TextView {
// Set the text
String text = format.format(new Date(time));
- setText(text);
+ maybeSetText(text);
// Schedule the next update
if (display == SHOW_TIME) {
@@ -258,7 +259,7 @@ public class DateTimeView extends TextView {
boolean past = (now >= mTimeMillis);
String result;
if (duration < MINUTE_IN_MILLIS) {
- setText(mNowText);
+ maybeSetText(mNowText);
mUpdateTimeMillis = mTimeMillis + MINUTE_IN_MILLIS + 1;
return;
} else if (duration < HOUR_IN_MILLIS) {
@@ -308,7 +309,19 @@ public class DateTimeView extends TextView {
mUpdateTimeMillis = mTimeMillis - millisIncrease * count + 1;
}
}
- setText(result);
+ maybeSetText(result);
+ }
+
+ /**
+ * Sets text only if the text has actually changed. This prevents needles relayouts of this
+ * view when set to wrap_content.
+ */
+ private void maybeSetText(String text) {
+ if (TextUtils.equals(getText(), text)) {
+ return;
+ }
+
+ setText(text);
}
/**
diff --git a/core/tests/coretests/src/android/widget/DateTimeViewTest.java b/core/tests/coretests/src/android/widget/DateTimeViewTest.java
index d0bd4b8b0bd5..14b48ed33494 100644
--- a/core/tests/coretests/src/android/widget/DateTimeViewTest.java
+++ b/core/tests/coretests/src/android/widget/DateTimeViewTest.java
@@ -16,14 +16,20 @@
package android.widget;
+import android.view.View;
+import android.view.ViewGroup;
+
import androidx.test.InstrumentationRegistry;
import androidx.test.annotation.UiThreadTest;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
+import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.time.Duration;
+
@RunWith(AndroidJUnit4.class)
@SmallTest
public class DateTimeViewTest {
@@ -39,7 +45,33 @@ public class DateTimeViewTest {
dateTimeView.detachedFromWindow();
}
+ @UiThreadTest
+ @Test
+ public void noChangeInRelativeText_doesNotTriggerRelayout() {
+ // Week in the future is chosen because it'll result in a stable string during this test
+ // run. This should be improved once the class is refactored to be more testable in
+ // respect of clock retrieval.
+ final long weekInTheFuture = System.currentTimeMillis() + Duration.ofDays(7).toMillis();
+ final TestDateTimeView dateTimeView = new TestDateTimeView();
+ dateTimeView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT));
+ dateTimeView.setShowRelativeTime(true);
+ dateTimeView.setTime(weekInTheFuture);
+ // View needs to be measured to request layout, skipping this would make this test pass
+ // always.
+ dateTimeView.measure(View.MeasureSpec.makeMeasureSpec(200, View.MeasureSpec.UNSPECIFIED),
+ View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.UNSPECIFIED));
+ dateTimeView.reset();
+
+ // This should not change the text content and thus no relayout is expected.
+ dateTimeView.setTime(weekInTheFuture + 1000);
+
+ Assert.assertFalse(dateTimeView.wasLayoutRequested());
+ }
+
private static class TestDateTimeView extends DateTimeView {
+ private boolean mRequestedLayout = false;
+
TestDateTimeView() {
super(InstrumentationRegistry.getContext());
}
@@ -51,5 +83,18 @@ public class DateTimeViewTest {
void detachedFromWindow() {
super.onDetachedFromWindow();
}
+
+ public void requestLayout() {
+ super.requestLayout();
+ mRequestedLayout = true;
+ }
+
+ public boolean wasLayoutRequested() {
+ return mRequestedLayout;
+ }
+
+ public void reset() {
+ mRequestedLayout = false;
+ }
}
}