Merge "Don't trigger full relayout if DateTimeView doesn't change" into tm-dev am: 06ac74c54f

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/17606881

Change-Id: I29f22c64b34f9801e9afe03f771b924b9e5333b7
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Lucas Dupin
2022-04-22 15:27:32 +00:00
committed by Automerger Merge Worker
2 changed files with 61 additions and 3 deletions

View File

@@ -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);
}
/**

View File

@@ -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;
}
}
}