Modify Comparator in ZonePicker
The previous method "compareTo" isn't locale-sensitive, it cannot sort the String in some other languages. So Collator is recommended to be applyed here. Bug: Sort doesn't work in some languages. Test: make RunSettingsRoboTests -j40 ROBOTEST_FILTER=ZonePickerComparatorTest Change-Id: Id107ab938cceefc77f9fb6918a0445fc92a0fcb7 Signed-off-by: tiansiming <tiansiming@xiaomi.com>
This commit is contained in:
@@ -22,6 +22,7 @@ import android.app.AlarmManager;
|
||||
import android.app.ListFragment;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
@@ -38,6 +39,7 @@ import com.android.settings.core.instrumentation.Instrumentable;
|
||||
import com.android.settings.core.instrumentation.VisibilityLoggerMixin;
|
||||
import com.android.settingslib.datetime.ZoneGetter;
|
||||
|
||||
import java.text.Collator;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
@@ -257,15 +259,21 @@ public class ZonePicker extends ListFragment implements Instrumentable {
|
||||
mVisibilityLoggerMixin.onPause();
|
||||
}
|
||||
|
||||
private static class MyComparator implements Comparator<Map<?, ?>> {
|
||||
@VisibleForTesting
|
||||
static class MyComparator implements Comparator<Map<?, ?>> {
|
||||
private final Collator mCollator;
|
||||
private String mSortingKey;
|
||||
private boolean mSortedByName;
|
||||
|
||||
public MyComparator(String sortingKey) {
|
||||
mCollator = Collator.getInstance();
|
||||
mSortingKey = sortingKey;
|
||||
mSortedByName = ZoneGetter.KEY_DISPLAY_LABEL.equals(sortingKey);
|
||||
}
|
||||
|
||||
public void setSortingKey(String sortingKey) {
|
||||
mSortingKey = sortingKey;
|
||||
mSortedByName = ZoneGetter.KEY_DISPLAY_LABEL.equals(sortingKey);
|
||||
}
|
||||
|
||||
public int compare(Map<?, ?> map1, Map<?, ?> map2) {
|
||||
@@ -282,8 +290,12 @@ public class ZonePicker extends ListFragment implements Instrumentable {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mSortedByName) {
|
||||
return mCollator.compare(value1, value2);
|
||||
} else {
|
||||
return ((Comparable) value1).compareTo(value2);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isComparable(Object value) {
|
||||
return (value != null) && (value instanceof Comparable);
|
||||
|
@@ -0,0 +1,123 @@
|
||||
package com.android.settings.datetime;
|
||||
|
||||
import com.android.settings.datetime.ZonePicker;
|
||||
import com.android.settings.testutils.SettingsRobolectricTestRunner;
|
||||
import com.android.settings.TestConfig;
|
||||
import com.android.settingslib.datetime.ZoneGetter;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.robolectric.annotation.Config;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
@RunWith(SettingsRobolectricTestRunner.class)
|
||||
@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
|
||||
public class ZonePickerComparatorTest {
|
||||
|
||||
// Strings in Chinese are sorted by alphabet order of their Pinyin.
|
||||
// "伦敦" -> "lundun"; "纽约" -> "niuyue"; "悉尼" -> "xini"
|
||||
// "开罗" -> "kailuo"; "雅典" -> "yadian"; "上海" -> "shanghai"
|
||||
private static final String[] TEST_CHINESE_NAME =
|
||||
new String[]{"伦敦", "纽约", "悉尼", "开罗", "雅典", "上海"};
|
||||
private static final String[] ORDERED_CHINESE_NAME =
|
||||
new String[]{"开罗", "伦敦", "纽约", "上海", "悉尼", "雅典"};
|
||||
|
||||
private static final String[] TEST_ENGLISH_NAME =
|
||||
new String[]{"London", "New York", "Sydney", "Cairo", "Athens", "Shanghai"};
|
||||
private static final String[] ORDERED_ENGLISH_NAME =
|
||||
new String[]{"Athens", "Cairo", "London", "New York", "Shanghai", "Sydney"};
|
||||
|
||||
private static final Locale INIT_LOCALE = Locale.getDefault();
|
||||
|
||||
private Map<String, List> mTestDataMap;
|
||||
private List<Map<String, Object>> mTestList;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mTestDataMap = new HashMap<>();
|
||||
mTestDataMap.put("zh_CN", Arrays.asList(TEST_CHINESE_NAME));
|
||||
mTestDataMap.put("en_US", Arrays.asList(TEST_ENGLISH_NAME));
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
Locale.setDefault(INIT_LOCALE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComparator_sortChineseString() {
|
||||
String sortKey = ZoneGetter.KEY_DISPLAY_LABEL;
|
||||
mTestList = getMockZonesList("zh_CN");
|
||||
Locale.setDefault(new Locale("zh"));
|
||||
final ZonePicker.MyComparator comparator = new ZonePicker.MyComparator(sortKey);
|
||||
assertThat(comparator).isNotNull();
|
||||
Collections.sort(mTestList, comparator);
|
||||
for (int i = 0; i < mTestList.size(); i++) {
|
||||
assertThat(mTestList.get(i).get(sortKey).toString())
|
||||
.isEqualTo(ORDERED_CHINESE_NAME[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComparator_sortEnglishString() {
|
||||
String sortKey = ZoneGetter.KEY_DISPLAY_LABEL;
|
||||
mTestList = getMockZonesList("en_US");
|
||||
Locale.setDefault(new Locale("en"));
|
||||
final ZonePicker.MyComparator comparator = new ZonePicker.MyComparator(sortKey);
|
||||
assertThat(comparator).isNotNull();
|
||||
Collections.sort(mTestList, comparator);
|
||||
for (int i = 0; i < mTestList.size(); i++) {
|
||||
assertThat(mTestList.get(i).get(sortKey).toString())
|
||||
.isEqualTo(ORDERED_ENGLISH_NAME[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComparator_sortInteger() {
|
||||
String sortKey = ZoneGetter.KEY_OFFSET;
|
||||
// TestList of any locale can be selected to test integer sorting.
|
||||
mTestList = getMockZonesList("en_US");
|
||||
final ZonePicker.MyComparator comparator = new ZonePicker.MyComparator(sortKey);
|
||||
assertThat(comparator).isNotNull();
|
||||
Collections.sort(mTestList, comparator);
|
||||
for (int i = 0; i < mTestList.size(); i++) {
|
||||
assertThat(mTestList.get(i).get(sortKey)).isEqualTo(i);
|
||||
}
|
||||
}
|
||||
|
||||
private List<Map<String, Object>> getMockZonesList(String locale) {
|
||||
List<Map<String, Object>> zones = new ArrayList<>();
|
||||
List<String> testData = mTestDataMap.get(locale);
|
||||
TimeZone tz = TimeZone.getDefault();
|
||||
int testSize = testData.size();
|
||||
for (int i = 0; i < testSize; i++) {
|
||||
zones.add(createMockDisplayEntry(tz, "GMT+08:00",
|
||||
testData.get(i), testSize - i - 1));
|
||||
}
|
||||
return zones;
|
||||
}
|
||||
|
||||
private Map<String, Object> createMockDisplayEntry(
|
||||
TimeZone tz, CharSequence gmtOffsetText, CharSequence displayName, int offsetMillis) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put(ZoneGetter.KEY_ID, tz.getID());
|
||||
map.put(ZoneGetter.KEY_DISPLAYNAME, displayName.toString());
|
||||
map.put(ZoneGetter.KEY_DISPLAY_LABEL, displayName);
|
||||
map.put(ZoneGetter.KEY_GMT, gmtOffsetText.toString());
|
||||
map.put(ZoneGetter.KEY_OFFSET_LABEL, gmtOffsetText);
|
||||
map.put(ZoneGetter.KEY_OFFSET, offsetMillis);
|
||||
return map;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user