perf: refresh only active root tab data on realtime events
This commit is contained in:
@@ -360,7 +360,150 @@ public class MainActivity extends AppCompatActivity {
|
||||
}
|
||||
|
||||
void refreshCurrentTab() {
|
||||
refreshAllData(sessionData);
|
||||
if ("devices".equals(activeTab)) {
|
||||
refreshDevicesData();
|
||||
return;
|
||||
}
|
||||
if ("me".equals(activeTab)) {
|
||||
refreshMeData();
|
||||
return;
|
||||
}
|
||||
refreshConversationsData();
|
||||
}
|
||||
|
||||
void refreshConversationsData() {
|
||||
startRefreshing(true);
|
||||
executor.execute(() -> {
|
||||
try {
|
||||
JSONObject session = ensureActiveSession();
|
||||
BossApiClient.ApiResponse conversations = null;
|
||||
boolean conversationsOk = false;
|
||||
try {
|
||||
conversations = apiClient.getConversations();
|
||||
conversationsOk = conversations.ok();
|
||||
} catch (Exception ignored) {
|
||||
conversationsOk = false;
|
||||
}
|
||||
if (!conversationsOk) {
|
||||
try {
|
||||
BossApiClient.ApiResponse fallbackConversations = apiClient.getConversationHome();
|
||||
if (fallbackConversations.ok()) {
|
||||
conversations = fallbackConversations;
|
||||
conversationsOk = true;
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
conversationsOk = false;
|
||||
}
|
||||
}
|
||||
|
||||
BossApiClient.ApiResponse finalConversations = conversations;
|
||||
final boolean finalConversationsOk = conversationsOk;
|
||||
runOnUiThread(() -> {
|
||||
sessionData = session;
|
||||
conversationsData = WechatSurfaceMapper.resolveRefreshValue(
|
||||
conversationsData,
|
||||
finalConversations == null ? null : finalConversations.json.optJSONArray("conversations"),
|
||||
finalConversationsOk
|
||||
);
|
||||
maybeApplyPreferredEntry();
|
||||
renderCurrentTab();
|
||||
startRefreshing(false);
|
||||
if (!finalConversationsOk) {
|
||||
showMessage("刷新失败,请稍后重试");
|
||||
}
|
||||
});
|
||||
} catch (Exception error) {
|
||||
runOnUiThread(() -> handleSessionRefreshFailure());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void refreshDevicesData() {
|
||||
startRefreshing(true);
|
||||
executor.execute(() -> {
|
||||
try {
|
||||
JSONObject session = ensureActiveSession();
|
||||
BossApiClient.ApiResponse devices = null;
|
||||
boolean devicesOk = false;
|
||||
try {
|
||||
devices = apiClient.getDevices();
|
||||
devicesOk = devices.ok();
|
||||
} catch (Exception ignored) {
|
||||
devicesOk = false;
|
||||
}
|
||||
|
||||
BossApiClient.ApiResponse finalDevices = devices;
|
||||
final boolean finalDevicesOk = devicesOk;
|
||||
runOnUiThread(() -> {
|
||||
sessionData = session;
|
||||
devicesData = WechatSurfaceMapper.resolveRefreshValue(
|
||||
devicesData,
|
||||
finalDevices == null ? null : finalDevices.json.optJSONArray("devices"),
|
||||
finalDevicesOk
|
||||
);
|
||||
renderCurrentTab();
|
||||
startRefreshing(false);
|
||||
if (!finalDevicesOk) {
|
||||
showMessage("刷新失败,请稍后重试");
|
||||
}
|
||||
});
|
||||
} catch (Exception error) {
|
||||
runOnUiThread(() -> handleSessionRefreshFailure());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void refreshMeData() {
|
||||
startRefreshing(true);
|
||||
executor.execute(() -> {
|
||||
try {
|
||||
JSONObject session = ensureActiveSession();
|
||||
BossApiClient.ApiResponse ota = null;
|
||||
BossApiClient.ApiResponse settings = null;
|
||||
boolean otaOk = false;
|
||||
boolean settingsOk = false;
|
||||
try {
|
||||
ota = apiClient.getOtaStatus();
|
||||
otaOk = ota.ok();
|
||||
} catch (Exception ignored) {
|
||||
otaOk = false;
|
||||
}
|
||||
try {
|
||||
settings = apiClient.getSettings();
|
||||
settingsOk = settings.ok();
|
||||
} catch (Exception ignored) {
|
||||
settingsOk = false;
|
||||
}
|
||||
|
||||
BossApiClient.ApiResponse finalOta = ota;
|
||||
BossApiClient.ApiResponse finalSettings = settings;
|
||||
final boolean finalOtaOk = otaOk;
|
||||
final boolean finalSettingsOk = settingsOk;
|
||||
runOnUiThread(() -> {
|
||||
sessionData = session;
|
||||
otaData = WechatSurfaceMapper.resolveRefreshValue(
|
||||
otaData,
|
||||
finalOta == null ? null : finalOta.json,
|
||||
finalOtaOk
|
||||
);
|
||||
JSONObject settingsPayload = finalSettings == null ? null : finalSettings.json.optJSONObject("settings");
|
||||
JSONObject userPayload = finalSettings == null ? null : finalSettings.json.optJSONObject("user");
|
||||
if (finalSettingsOk && settingsPayload != null) {
|
||||
preferredEntryTab = settingsPayload.optString("preferredEntryPoint", "conversations");
|
||||
}
|
||||
if (finalSettingsOk) {
|
||||
updateBoundDeviceState(userPayload);
|
||||
}
|
||||
renderCurrentTab();
|
||||
startRefreshing(false);
|
||||
if (!finalOtaOk && !finalSettingsOk) {
|
||||
showMessage("刷新失败,请稍后重试");
|
||||
}
|
||||
});
|
||||
} catch (Exception error) {
|
||||
runOnUiThread(() -> handleSessionRefreshFailure());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void handleRealtimeEvent(BossRealtimeEvent event) {
|
||||
@@ -569,6 +712,40 @@ public class MainActivity extends AppCompatActivity {
|
||||
});
|
||||
}
|
||||
|
||||
private JSONObject ensureActiveSession() throws IOException {
|
||||
JSONObject session = sessionData;
|
||||
if (session != null) {
|
||||
return session;
|
||||
}
|
||||
try {
|
||||
BossApiClient.ApiResponse sessionResponse = apiClient.getSession();
|
||||
if (!sessionResponse.ok()) {
|
||||
sessionResponse = apiClient.restoreSession();
|
||||
}
|
||||
if (!sessionResponse.ok()) {
|
||||
throw new IOException("SESSION_UNAVAILABLE");
|
||||
}
|
||||
JSONObject restored = sessionResponse.json.optJSONObject("session");
|
||||
if (restored == null) {
|
||||
throw new IOException("SESSION_UNAVAILABLE");
|
||||
}
|
||||
return restored;
|
||||
} catch (IOException error) {
|
||||
throw error;
|
||||
} catch (Exception error) {
|
||||
throw new IOException("SESSION_UNAVAILABLE", error);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleSessionRefreshFailure() {
|
||||
startRefreshing(false);
|
||||
sessionData = null;
|
||||
conversationsData = null;
|
||||
devicesData = null;
|
||||
otaData = null;
|
||||
showLogin("当前登录已失效或同步失败,请重新点击登录。");
|
||||
}
|
||||
|
||||
private void showLogin(String hint) {
|
||||
loginPanel.setVisibility(View.VISIBLE);
|
||||
contentPanel.setVisibility(View.GONE);
|
||||
|
||||
@@ -28,7 +28,9 @@ public class MainActivityRealtimeTest {
|
||||
);
|
||||
Shadows.shadowOf(activity.getMainLooper()).idle();
|
||||
|
||||
assertEquals(1, activity.refreshCount);
|
||||
assertEquals(1, activity.conversationRefreshCount);
|
||||
assertEquals(0, activity.deviceRefreshCount);
|
||||
assertEquals(0, activity.meRefreshCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -45,7 +47,8 @@ public class MainActivityRealtimeTest {
|
||||
);
|
||||
Shadows.shadowOf(activity.getMainLooper()).idle();
|
||||
|
||||
assertEquals(0, activity.refreshCount);
|
||||
assertEquals(0, activity.conversationRefreshCount);
|
||||
assertEquals(0, activity.deviceRefreshCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -62,7 +65,7 @@ public class MainActivityRealtimeTest {
|
||||
);
|
||||
Shadows.shadowOf(activity.getMainLooper()).idle();
|
||||
|
||||
assertEquals(0, activity.refreshCount);
|
||||
assertEquals(0, activity.conversationRefreshCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -82,7 +85,8 @@ public class MainActivityRealtimeTest {
|
||||
);
|
||||
Shadows.shadowOf(activity.getMainLooper()).idle();
|
||||
|
||||
assertEquals(1, activity.refreshCount);
|
||||
assertEquals(1, activity.conversationRefreshCount);
|
||||
assertEquals(0, activity.deviceRefreshCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -113,15 +117,78 @@ public class MainActivityRealtimeTest {
|
||||
);
|
||||
Shadows.shadowOf(activity.getMainLooper()).idle();
|
||||
|
||||
assertEquals(2, activity.refreshCount);
|
||||
assertEquals(2, activity.conversationRefreshCount);
|
||||
assertEquals(0, activity.deviceRefreshCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void devicesRealtimeEventRefreshesVisibleDevicesTabOnly() throws Exception {
|
||||
TestMainActivity activity = Robolectric.buildActivity(TestMainActivity.class).setup().resume().get();
|
||||
ReflectionHelpers.callInstanceMethod(activity, "showContent");
|
||||
ReflectionHelpers.callInstanceMethod(
|
||||
activity,
|
||||
"setActiveTab",
|
||||
ReflectionHelpers.ClassParameter.from(String.class, "devices"),
|
||||
ReflectionHelpers.ClassParameter.from(boolean.class, false)
|
||||
);
|
||||
ReflectionHelpers.callInstanceMethod(
|
||||
activity,
|
||||
"handleRealtimeEvent",
|
||||
ReflectionHelpers.ClassParameter.from(
|
||||
BossRealtimeEvent.class,
|
||||
new BossRealtimeEvent("devices.updated", new JSONObject().put("deviceId", "mac-studio"))
|
||||
)
|
||||
);
|
||||
Shadows.shadowOf(activity.getMainLooper()).idle();
|
||||
|
||||
assertEquals(0, activity.conversationRefreshCount);
|
||||
assertEquals(1, activity.deviceRefreshCount);
|
||||
assertEquals(0, activity.meRefreshCount);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void otaRealtimeEventRefreshesVisibleMeTabOnly() throws Exception {
|
||||
TestMainActivity activity = Robolectric.buildActivity(TestMainActivity.class).setup().resume().get();
|
||||
ReflectionHelpers.callInstanceMethod(activity, "showContent");
|
||||
ReflectionHelpers.callInstanceMethod(
|
||||
activity,
|
||||
"setActiveTab",
|
||||
ReflectionHelpers.ClassParameter.from(String.class, "me"),
|
||||
ReflectionHelpers.ClassParameter.from(boolean.class, false)
|
||||
);
|
||||
ReflectionHelpers.callInstanceMethod(
|
||||
activity,
|
||||
"handleRealtimeEvent",
|
||||
ReflectionHelpers.ClassParameter.from(
|
||||
BossRealtimeEvent.class,
|
||||
new BossRealtimeEvent("ota.updated", new JSONObject())
|
||||
)
|
||||
);
|
||||
Shadows.shadowOf(activity.getMainLooper()).idle();
|
||||
|
||||
assertEquals(0, activity.conversationRefreshCount);
|
||||
assertEquals(0, activity.deviceRefreshCount);
|
||||
assertEquals(1, activity.meRefreshCount);
|
||||
}
|
||||
|
||||
public static class TestMainActivity extends MainActivity {
|
||||
int refreshCount;
|
||||
int conversationRefreshCount;
|
||||
int deviceRefreshCount;
|
||||
int meRefreshCount;
|
||||
|
||||
@Override
|
||||
void refreshCurrentTab() {
|
||||
refreshCount += 1;
|
||||
void refreshConversationsData() {
|
||||
conversationRefreshCount += 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
void refreshDevicesData() {
|
||||
deviceRefreshCount += 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
void refreshMeData() {
|
||||
meRefreshCount += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user