diff options
| -rw-r--r-- | core/java/android/widget/DateTimeView.java | 19 | ||||
| -rw-r--r-- | core/tests/coretests/src/android/widget/DateTimeViewTest.java | 45 |
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; + } } } |