perf: coalesce root tab realtime refresh bursts
This commit is contained in:
@@ -104,6 +104,8 @@ public class MainActivity extends AppCompatActivity {
|
||||
private boolean conversationQuickActionsVisible = false;
|
||||
private boolean conversationAutoRefreshArmed = false;
|
||||
private boolean conversationAutoRefreshEnabled = false;
|
||||
private boolean rootTabRefreshInFlight = false;
|
||||
private boolean pendingRootTabRefresh = false;
|
||||
private final java.util.HashMap<String, Long> recentRealtimeEventTimestamps = new java.util.HashMap<>();
|
||||
private final Set<String> selectedConversationProjectIds = new LinkedHashSet<>();
|
||||
private @Nullable RootPagerAdapter rootPagerAdapter;
|
||||
@@ -362,6 +364,11 @@ public class MainActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
void refreshCurrentTab() {
|
||||
if (rootTabRefreshInFlight) {
|
||||
pendingRootTabRefresh = true;
|
||||
return;
|
||||
}
|
||||
rootTabRefreshInFlight = true;
|
||||
if ("devices".equals(activeTab)) {
|
||||
refreshDevicesData();
|
||||
return;
|
||||
@@ -413,9 +420,13 @@ public class MainActivity extends AppCompatActivity {
|
||||
if (!finalConversationsOk) {
|
||||
showMessage("刷新失败,请稍后重试");
|
||||
}
|
||||
completeRealtimeTabRefresh();
|
||||
});
|
||||
} catch (Exception error) {
|
||||
runOnUiThread(() -> handleSessionRefreshFailure());
|
||||
runOnUiThread(() -> {
|
||||
handleSessionRefreshFailure();
|
||||
completeRealtimeTabRefresh();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -448,9 +459,13 @@ public class MainActivity extends AppCompatActivity {
|
||||
if (!finalDevicesOk) {
|
||||
showMessage("刷新失败,请稍后重试");
|
||||
}
|
||||
completeRealtimeTabRefresh();
|
||||
});
|
||||
} catch (Exception error) {
|
||||
runOnUiThread(() -> handleSessionRefreshFailure());
|
||||
runOnUiThread(() -> {
|
||||
handleSessionRefreshFailure();
|
||||
completeRealtimeTabRefresh();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -501,13 +516,26 @@ public class MainActivity extends AppCompatActivity {
|
||||
if (!finalOtaOk && !finalSettingsOk) {
|
||||
showMessage("刷新失败,请稍后重试");
|
||||
}
|
||||
completeRealtimeTabRefresh();
|
||||
});
|
||||
} catch (Exception error) {
|
||||
runOnUiThread(() -> handleSessionRefreshFailure());
|
||||
runOnUiThread(() -> {
|
||||
handleSessionRefreshFailure();
|
||||
completeRealtimeTabRefresh();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void completeRealtimeTabRefresh() {
|
||||
rootTabRefreshInFlight = false;
|
||||
if (!pendingRootTabRefresh) {
|
||||
return;
|
||||
}
|
||||
pendingRootTabRefresh = false;
|
||||
refreshCurrentTab();
|
||||
}
|
||||
|
||||
void handleRealtimeEvent(BossRealtimeEvent event) {
|
||||
if (event == null || event.eventName.isEmpty()) {
|
||||
return;
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.hyzq.boss;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import android.os.Looper;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -11,6 +12,8 @@ import org.robolectric.Shadows;
|
||||
import org.robolectric.annotation.Config;
|
||||
import org.robolectric.util.ReflectionHelpers;
|
||||
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
@RunWith(RobolectricTestRunner.class)
|
||||
@Config(sdk = 34)
|
||||
public class MainActivityRealtimeTest {
|
||||
@@ -171,6 +174,62 @@ public class MainActivityRealtimeTest {
|
||||
assertEquals(1, activity.meRefreshCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void burstConversationRealtimeEventsCoalesceIntoSingleFollowUpRefresh() throws Exception {
|
||||
TestMainActivity activity = Robolectric.buildActivity(TestMainActivity.class).setup().resume().get();
|
||||
ReflectionHelpers.callInstanceMethod(activity, "showContent");
|
||||
ReflectionHelpers.setField(activity, "rootTabRefreshInFlight", true);
|
||||
|
||||
ReflectionHelpers.callInstanceMethod(
|
||||
activity,
|
||||
"handleRealtimeEvent",
|
||||
ReflectionHelpers.ClassParameter.from(
|
||||
BossRealtimeEvent.class,
|
||||
new BossRealtimeEvent("conversation.updated", new JSONObject().put("projectId", "project-1"))
|
||||
)
|
||||
);
|
||||
Shadows.shadowOf(activity.getMainLooper()).idle();
|
||||
|
||||
ReflectionHelpers.callInstanceMethod(
|
||||
activity,
|
||||
"handleRealtimeEvent",
|
||||
ReflectionHelpers.ClassParameter.from(
|
||||
BossRealtimeEvent.class,
|
||||
new BossRealtimeEvent("project.messages.updated", new JSONObject().put("projectId", "project-1"))
|
||||
)
|
||||
);
|
||||
ReflectionHelpers.callInstanceMethod(
|
||||
activity,
|
||||
"handleRealtimeEvent",
|
||||
ReflectionHelpers.ClassParameter.from(
|
||||
BossRealtimeEvent.class,
|
||||
new BossRealtimeEvent("conversation.context_indicator.updated", new JSONObject().put("projectId", "project-1"))
|
||||
)
|
||||
);
|
||||
Shadows.shadowOf(activity.getMainLooper()).idle();
|
||||
|
||||
assertEquals(0, activity.conversationRefreshCount);
|
||||
|
||||
activity.completeRealtimeTabRefresh();
|
||||
waitFor(() -> activity.conversationRefreshCount == 1);
|
||||
|
||||
assertEquals(1, activity.conversationRefreshCount);
|
||||
assertEquals(0, activity.deviceRefreshCount);
|
||||
assertEquals(0, activity.meRefreshCount);
|
||||
}
|
||||
|
||||
private static void waitFor(BooleanSupplier condition) throws Exception {
|
||||
long deadlineAt = System.currentTimeMillis() + 2_000L;
|
||||
while (System.currentTimeMillis() < deadlineAt) {
|
||||
Shadows.shadowOf(Looper.getMainLooper()).idle();
|
||||
if (condition.getAsBoolean()) {
|
||||
return;
|
||||
}
|
||||
Thread.sleep(20L);
|
||||
}
|
||||
throw new AssertionError("condition not met before timeout");
|
||||
}
|
||||
|
||||
public static class TestMainActivity extends MainActivity {
|
||||
int conversationRefreshCount;
|
||||
int deviceRefreshCount;
|
||||
@@ -179,16 +238,19 @@ public class MainActivityRealtimeTest {
|
||||
@Override
|
||||
void refreshConversationsData() {
|
||||
conversationRefreshCount += 1;
|
||||
completeRealtimeTabRefresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
void refreshDevicesData() {
|
||||
deviceRefreshCount += 1;
|
||||
completeRealtimeTabRefresh();
|
||||
}
|
||||
|
||||
@Override
|
||||
void refreshMeData() {
|
||||
meRefreshCount += 1;
|
||||
completeRealtimeTabRefresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user