我是 Rx 编程的新手(到目前为止我玩得很开心^^)。我正在尝试将 AsyncTask 调用转换为 Rx 函数。
我的功能:
- 获取所有已安装的应用
- 标准化标签
- 按字母顺序对所有内容进行排序
- 按字母组排列它们(这是一个 Multimap(letter, list of apps))并将结果传递给适配器以显示所有内容。
以下是我到目前为止对 Rx 所做的事情:
Observable.from(getInstalledApps(getActivity(), false))
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.map(new Func1<ResolvedActivityInfoWrapper, ResolvedActivityInfoWrapper>() {
@Override
public ResolvedActivityInfoWrapper call(ResolvedActivityInfoWrapper act) {
// Normalize labels
act.setLabel(Normalizer.normalize(act.getLabel(getPackageManager()).replace(String.valueOf((char) 160), "").trim(), Normalizer.Form.NFD).replaceAll("\\p{M}", ""));
return act;
}
})
.toList()
.subscribe(new Observer<List<ResolvedActivityInfoWrapper>>() {
List<ResolvedActivityInfoWrapper> list;
@Override
public void onCompleted() {
Observable.from(list).groupBy(new Func1<ResolvedActivityInfoWrapper, String>() {
@Override
public String call(ResolvedActivityInfoWrapper input) {
//Get groups by letter
String label = input.getLabel(getPackageManager());
if (!TextUtils.isEmpty(label)) {
String firstChar = label.substring(0, 1);
if (pattern.matcher(firstChar).matches()) {
return firstChar.toUpperCase();
}
}
return "#";
}
}).subscribe(this); // implementation below
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(List<ResolvedActivityInfoWrapper> list) {
Collections.sort(list, new Comparator<ActivityInfoWrapper>() {
@Override
// Sort all the apps in the list, not sure it's a good way to do it
public int compare(ActivityInfoWrapper info1, ActivityInfoWrapper info2) {
return info1.getLabel(getPackageManager()).compareToIgnoreCase(info2.getLabel(getPackageManager()));
}
});
this.list = list;
}
});
一旦我按字母分组,完成后我订阅:
@Override
public void onCompleted() {
//display the apps
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(GroupedObservable<String, ResolvedActivityInfoWrapper> input) {
//For each list of apps by letter i subscribe with an observer that will handle those apps (observer code below)
input.subscribe(new TestObserver(input.getKey()));
}
观察员:
private class TestObserver implements Observer<ResolvedActivityInfoWrapper> {
List<ResolvedActivityInfoWrapper> list;
String letter;
public TestObserver(String letter) {
list = new ArrayList<>();
this.letter = letter;
}
@Override
public void onCompleted() {
adapter.addData(letter, list);
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(ResolvedActivityInfoWrapper input) {
list.add(input);
}
}
一切正常,除了一个问题:观察者的 onCompleted 调用顺序不正确。所以我得到了我所有的应用程序,按字母排序,但是这些组的显示顺序不正确(首先是 C,然后是 Y,然后是 M 等)。
我想代码中有很多错误,你能帮我解决这个问题,也许能理解这一切是如何工作的吗?
谢谢
更新: 按照评论部分中的建议(感谢人们),这是我在标准化标签后尝试的内容:
Observable.from(list).groupBy(new Func1<ResolvedActivityInfoWrapper, String>() {
@Override
public String call(ResolvedActivityInfoWrapper input) {
String label = input.getLabel(getPackageManager());
if (!TextUtils.isEmpty(label)) {
String firstChar = label.substring(0, 1);
if (pattern.matcher(firstChar).matches()) {
return firstChar.toUpperCase();
}
}
return "#";
}
})
.toSortedList(new Func2<GroupedObservable<String, ResolvedActivityInfoWrapper>, GroupedObservable<String, ResolvedActivityInfoWrapper>, Integer>() {
@Override
public Integer call(GroupedObservable<String, ResolvedActivityInfoWrapper> obs1, GroupedObservable<String, ResolvedActivityInfoWrapper> obs2) {
return obs1.getKey().compareToIgnoreCase(obs2.getKey());
}
})
.subscribe(new Observer<List<GroupedObservable<String, ResolvedActivityInfoWrapper>>>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(List<GroupedObservable<String, ResolvedActivityInfoWrapper>> input) {
String test = input.get(0).getKey();
}
});
但它永远不会进入比较功能。