Loading core/java/android/widget/DateTimeView.java +16 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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) { Loading Loading @@ -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); } /** Loading core/tests/coretests/src/android/widget/DateTimeViewTest.java +45 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading @@ -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()); } Loading @@ -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; } } } Loading
core/java/android/widget/DateTimeView.java +16 −3 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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) { Loading Loading @@ -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) { Loading Loading @@ -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); } /** Loading
core/tests/coretests/src/android/widget/DateTimeViewTest.java +45 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading @@ -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()); } Loading @@ -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; } } }