在Observable的onNext中初始化RecyclerView项是否安全

时间:2016-02-04 11:13:22

标签: android android-recyclerview rx-java

我使用RecyclerView来显示包含日期的项目列表,并在非UI线程上格式化我想要使用RxJava的日期。 这是我的Observable

的代码
public Observable<String> getDateFormatObservable(){
        return Observable.create(new Observable.OnSubscribe<String>() {
            @Override
            public void call(Subscriber<? super String> subscriber) {
                if(date == null){
                    if(!subscriber.isUnsubscribed()){
                        subscriber.onNext(dateStr);
                        subscriber.onCompleted();
                    }
                    return;
                }

                String formatedDate = "";

                if(DateUtils.isToday(date)){
                    formatedDate = DateFormat.format("H:m", date).toString();
                } else {
                    formatedDate = DateFormat.format("d MMM yyyy", date).toString();
                }

                if(!subscriber.isUnsubscribed()){
                    subscriber.onNext(formatedDate);
                    subscriber.onCompleted();
                }
            }
        });
    }

这是我订阅者的代码:

public void initDate(final TextView dateTv){
    getDateFormatObservable()
            .subscribeOn(Schedulers.computation())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Action1<String>() {
                @Override
                public void call(String s) {
                    dateTv.setText(s);
                }
            });
}

我从initDate调用此onBindViewHolder方法,并将相应的TextView传递给它。

所以问题是 - 这样做是否安全?由于回收会有问题吗?例如,如果我快速滚动,是否有错误日期设置为TextView的情况?

P.S。当我现在测试时,似乎一切正常,但我认为当相应的TextView已经在屏幕外并且被回收并且可以设置此日期时,可能会出现调用日期OnNext的情况。错误的TextView。但令人惊讶的是,它似乎没有发生。

1 个答案:

答案 0 :(得分:1)

一般来说,在滚动期间准备数据是非常糟糕的主意(CursorAdapter是另一个故事)。我想在你的情况下一切正常,因为你的代码

if(DateUtils.isToday(date)){
    formatedDate = DateFormat.format("H:m", date).toString();
} else {
    formatedDate = DateFormat.format("d MMM yyyy", date).toString();
}

它只是执行得非常快。不知道DateUtils.isToday中发生了什么,但我认为你可以在UI Thread中运行它,一切都会正常运行,你的代码会更简单。

另一个问题是,如果没有缓存,你就会不断构建formatedDate,这只是毫无意义。

最常见的方法是按页面加载数据并将其传递给适配器。您可以创建Pojo/Model对象并将数据存储在其中:

public class Model{
    String formatedDate;
    //other fields
}

您可以创建返回模型列表的方法,而不是调用getDateFormatObservable,这些方法已经包含可见数量的列表(RecyclerView)项目的所有必要数据:

Observable<List<Model>> getModels(long fromDate, long toDate);

当用户到达列表末尾时,您需要调用该方法来加载下一页数据。