perf: diff root list updates by stable item keys

This commit is contained in:
kris
2026-04-05 08:18:15 +08:00
parent 6083079be9
commit 71aa1a7143
2 changed files with 242 additions and 67 deletions

View File

@@ -0,0 +1,87 @@
package com.hyzq.boss;
import static org.junit.Assert.assertEquals;
import android.view.View;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Config;
import java.util.List;
import androidx.recyclerview.widget.RecyclerView;
@RunWith(RobolectricTestRunner.class)
@Config(sdk = 34)
public class MainActivityRootListAdapterTest {
@Test
public void submitUsesItemDiffInsteadOfFullDatasetChange() {
MainActivity.RootListAdapter adapter = new MainActivity.RootListAdapter();
RecordingObserver observer = new RecordingObserver();
adapter.registerAdapterDataObserver(observer);
adapter.submit(List.of(
fakeItem("conversation:a", "same"),
fakeItem("conversation:b", "before")
));
observer.reset();
adapter.submit(List.of(
fakeItem("conversation:a", "same"),
fakeItem("conversation:b", "after")
));
assertEquals(0, observer.changedAllCount);
assertEquals(1, observer.itemRangeChangedCount);
assertEquals(1, observer.lastChangedPosition);
assertEquals(1, observer.lastChangedCount);
}
private static MainActivity.RootListItem fakeItem(String key, String signature) {
return new MainActivity.RootListItem() {
@Override
public String stableKey() {
return key;
}
@Override
public String contentSignature() {
return signature;
}
@Override
public View build() {
return new View(RuntimeEnvironment.getApplication());
}
};
}
private static final class RecordingObserver extends RecyclerView.AdapterDataObserver {
int changedAllCount;
int itemRangeChangedCount;
int lastChangedPosition = -1;
int lastChangedCount = -1;
void reset() {
changedAllCount = 0;
itemRangeChangedCount = 0;
lastChangedPosition = -1;
lastChangedCount = -1;
}
@Override
public void onChanged() {
changedAllCount += 1;
}
@Override
public void onItemRangeChanged(int positionStart, int itemCount) {
itemRangeChangedCount += 1;
lastChangedPosition = positionStart;
lastChangedCount = itemCount;
}
}
}