oxoooo / data-binding-support

Provides useful subclasses from Support Library that work with Data Binding.
MIT License
33 stars 4 forks source link

BindingRecyclerView.ListAdapter: when source ObservableList changes outside UI thread #1

Closed rhyek closed 8 years ago

rhyek commented 8 years ago

I'm using an ObservableArrayList that changes on some network events. Whenever a change occurs, I'm getting warnings about them happening outisde the UI thread and the RecyclerView isn't updating.

I made the following changes to widget/BindingRecyclerView at line 43 that fixes the problem for me, but I'd like to get some feedback on them:

        private Context context;
        protected final LayoutInflater inflater;
        protected final ObservableList<T> data;

        private final AtomicInteger refs = new AtomicInteger();

        private final ObservableList.OnListChangedCallback<ObservableList<T>> callback =
                new ObservableList.OnListChangedCallback<ObservableList<T>>() {
                    @Override
                    public void onChanged(ObservableList<T> sender) {
                        ((Activity)context).runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                notifyDataSetChanged();
                            }
                        });
                    }

                    @Override
                    public void onItemRangeChanged(ObservableList<T> sender,
                                                   final int positionStart, final int itemCount) {
                        ((Activity)context).runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                notifyItemRangeChanged(positionStart, itemCount);
                            }
                        });
                    }

                    @Override
                    public void onItemRangeInserted(ObservableList<T> sender,
                                                    final int positionStart, final int itemCount) {
                        ((Activity)context).runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                notifyItemRangeInserted(positionStart, itemCount);
                            }
                        });
                    }

                    @Override
                    public void onItemRangeMoved(ObservableList<T> sender,
                                                 final int fromPosition, final int toPosition, final int itemCount) {
                        ((Activity)context).runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                for (int i = 0; i < itemCount; i++) {
                                    notifyItemMoved(fromPosition + i, toPosition + i);
                                }
                            }
                        });
                    }

                    @Override
                    public void onItemRangeRemoved(ObservableList<T> sender,
                                                   final int positionStart, final int itemCount) {
                        ((Activity)context).runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                notifyItemRangeRemoved(positionStart, itemCount);
                            }
                        });
                    }
                };
xingrz commented 8 years ago

You may operate ObservableArrayList on main thread.

rhyek commented 8 years ago

Thanks. Like I said, I'm using an ObservableArrayList and I am consitently getting these warnings. I am unable to change the way my updates are coming in since they are triggered by a Server Sent Event, and as they happen throughout the life cycle of my app, I can't make them run on the UI thread themselves for performance/responsiveness reasons.

Since we're talking about a widget, wouldn't it be appropriate to ensure the notifications are running on the UI thread anyways?