在RecyclerView适配器内部使用RxJava

问题描述 投票:7回答:2

所以几周前,我问了一个问题:recyclerview periodic ui child updates

今天,我想使用Rxjava重构该功能。它实际上非常简单,我可以通过以下方式完成:

 @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {

                if (friend.getGameStatus().equals(GameStatus.INGAME)) {
                    holderOnline.startRepeatingTask();
                } else {
                    holderOnline.stopRepeatingTask();
                } 
    }


class MyViewHolderOnline extends RecyclerView.ViewHolder {

    private Subscription subscribe;

        public MyViewHolderOnline(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);

        }

        public void startRepeatingTask() {
            subscribe = Observable.interval(updateInterval, TimeUnit.MILLISECONDS)
                    .map(aLong -> current.getGameStatusToPrint())
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new Subscriber<String>() {
                        @Override public void onCompleted() { }
                        @Override public void onError(Throwable e) { }

                        @Override
                        public void onNext(String gameStatusToPrint) {
                            gameStatus.setText(gameStatusToPrint);
                        }
                    });
        }

        void stopRepeatingTask() {
            if(subscribe != null && !subscribe.isUnsubscribed())
                subscribe.unsubscribe();
        }
    }

但是问题不同。我有一个用活动实现的navigationDrawer,该活动在切换时已暂停且未销毁。因此,在我切换到不包含此适配器的活动之后,可观察对象将继续发送内容,因为它的周期间隔为可观察对象。所以我的问题是,我该怎么办?我需要在活动暂停时退订,但是我不知道该怎么办以及如何退订。有什么帮助或想法吗?

android rx-java
2个回答
1
投票

因此,如果我对您的理解正确,一种解决问题的方法是回答以下问题:在包含ActivityRecyclerView中,如何获得对当前显示的所有ViewHolder的引用/ bound?

例如,要停止所有更新,您可以在onPause()Activity中执行以下操作:

// assuming you are using a LinearLayoutManager:
final int firstVisibleIndex = mLinearLayoutManager.findFirstVisibleItemPosition();
final int lastVisibleIndex = mLinearLayoutManager.findLastVisibleItemPosition();

for (int i = firstVisibleIndex; i <= lastVisibleIndex; i++) {
    YourViewHolder viewHolder = (YourViewHolder) findViewHolderForAdapterPosition (i);
    viewHolder.stopRepeatingTask();
}

同样,您可以在onResumeActivity中重新启动任务。

BUT:既然我写了这篇文章,现在不确定在已绑定的ViewHolder可见区域之外(即第一个可见项目之前或之后)是否还有RecyclerView个但是使用这种方法无法实现。如果真是这种情况,您仍然可以遍历适配器中各项的所有索引,而只丢弃任何null返回值。


0
投票

我使用此示例

1-创建一个ViewModelVM_User的名称

public class VM_User {
    private String Name,Family;

    public String getName() {
        return Name;
    }

    public String getFamily() {
        return Family;
    }

    public void setName(String name) {
        Name = name;
    }

    public void setFamily(String family) {
        Family = family;
    }
}

Adapter上[2-为RecyclerView创建到UserAdapter的名称]

3-将此method写入getData

private Single<List<VM_User>> datas() {

        return Single.create(emitter -> {

            Thread thread = new Thread(() -> {

                try {

                    List<VM_User> users = new ArrayList<>();

                    for (int i=0;i<20;i++){

                        VM_User user=new VM_User();

                        user.setName("Diako"+i);
                        user.setFamily("Hasani"+i);

                        users.add(user);

                    }

                    emitter.onSuccess(users);


                } catch (Exception e) {

                    emitter.onError(e);

                }

            });

            thread.run();
        });
    }

4-将此method写入以将数据设置为RecyclerView

void SetRecycler(List<VM_User> users) {

        Observable<VM_User> list = Observable.fromIterable(users);

        list.subscribe(vm_user -> {

            //add user to `RecyclerView`
            userAdapter.AddUser(vm_user);

        }, throwable -> {

        }, () -> {

        });

    }

5-用于呼叫methods,写此method

void GetUsers() {
        Single<List<VM_User>> listSingle = datas();

        listSingle.subscribeWith(new DisposableSingleObserver<List<VM_User>>() {

            @Override
            public void onSuccess(List<VM_User> users) {
                SetRecycler(users);
            }

            @Override
            public void onError(Throwable e) {
                Toast.makeText(MainActivity.this, "Error", Toast.LENGTH_SHORT).show();
            }
        });
    }

6-将此objects与此RecyclerView相加

RecyclerView Recycler;
UserAdapter userAdapter;
LinearLayoutManager linearLayoutManager;

[7-在onCreate我的Activity中写此代码] >>

@SuppressLint("CheckResult")
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Recycler = findViewById(R.id.Recycler);
    linearLayoutManager = new LinearLayoutManager(getApplicationContext(), LinearLayoutManager.VERTICAL, false);

    List<VM_User> empty = new ArrayList<>();
    userAdapter = new UserAdapter(empty, getApplicationContext());
    Recycler.setAdapter(userAdapter);
    Recycler.setLayoutManager(linearLayoutManager);

    GetUsers();

}
© www.soinside.com 2019 - 2024. All rights reserved.