2

Im trying to replace my CustomListView with RecyclerView, but i am facing an issue calls IndexOutOfBoundsException: Inconsistency detected.

I use application service in order to update/change my entire list items every 10 seconds by getting data from server. But my RecyclerView crash everytime, when service making request, update contents and scrolling at the same time.

I know that this question has been already asked, but i still don't get an correct answer that solves my problem. So I decided to ask you guys again for help, before I go back to my CustomListView.

I have tried almost every single answer on this and this posts, but still no success.

Here is my Adapter:

public class EventAdapter extends RecyclerView.Adapter<EventAdapter.MyViewHolder> {

    private List<EventModel> eventList = new ArrayList<>();
    private Context context;
    public class MyViewHolder extends RecyclerView.ViewHolder {
       private TextView timeView, titleView;

        public MyViewHolder(View view) {
            super(view);
            titleView = (TextView) view.findViewById(R.id.txtListTitle);
            timeView = (TextView) view.findViewById(R.id.txtListTime);
        }
    }


    public EventAdapter(Context context, List<EventModel> eventList) {
        this.eventList = eventList;
        this.context = context;
    }

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.list_event_form, parent, false);

        return new MyViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        EventModel event = eventList.get(position);
        holder.titleView.setText(event.getTitle());
        holder.timeView.setText(event.getEndTime());
    }

    /*public void update(ArrayList<EventModel> list) {

        if (eventList != null) {
            eventList.clear();
            eventList.addAll(0,list);
        }
        else {
            eventList = list;
        }
        notifyDataSetChanged(); // this does not work
    }*/

    @Override
    public int getItemCount() {
        return eventList.size();
    }
}

Here is where i use RecyclerView:

    public class EventListFragment extends Fragment {
    private View view;

    private RecyclerView recyclerView;
    private LinearLayoutManager mLayoutManager;
    private EventAdapter eventAdapter;
    private ArrayList<EventModel> eventList;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        view = inflater.inflate(R.layout.fragment_event_list, container, false);
        return view;
    }

    @Override
    public void onResume() {
        super.onResume();
        setView();
        setControl();
    }

    private void setView() {
        recyclerView = (RecyclerView) view.findViewById(R.id.frg_recycler_view);
    }

    private void setControl() {
          if (eventAdapter == null && mLayoutManager == null) {
            eventList = new ArrayList<>();
            eventAdapter = new EventAdapter(getActivity().getApplicationContext(), eventList);
            mLayoutManager = new LinearLayoutManager(getActivity().getApplicationContext());
            recyclerView.setLayoutManager(mLayoutManager);
            recyclerView.setHasFixedSize(true);
            recyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), LinearLayoutManager.VERTICAL));
            recyclerView.setAdapter(eventAdapter);
        }

    public void eventToList() { // this will be called by service every 10 secs
        final RequestData requestData = new RequestData(getActivity());
        eventList.clear(); // clean data, before inserting new data
        requestData.getEventToday(new RequestData.VolleyCallback() {
            @Override
            public void onSuccess(JSONObject result) {
                for (int i = 0; i < result.length(); i++) {
                    try {
                        JSONObject item = result.getJSONObject(Integer.toString(i));
                        EventModel eventModel = new EventModel();
                        String title = item.getString("title");
                        String date = item.getString("date");

                        eventModel.setTitle(title);
                        eventModel.setDate(date);

                        eventList.add(eventModel);
                    } catch (JSONException e) {
                        Log.d(TAG, "error" + e.toString());
                        e.printStackTrace();
                    }
                }
                   // Log.d(TAG, "onSuccess: Update Currentdate");
                    eventAdapter.notifyDataSetChanged();
            }
        });
    }
}

And here is what I have got:

E/AndroidRuntime: FATAL EXCEPTION: main
              Process: com.example.longluong.mybbs, PID: 10469
              java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder{1b43c6c position=10 id=-1, oldPos=-1, pLpos:-1 no parent}
                  at android.support.v7.widget.RecyclerView$Recycler.validateViewHolderForOffsetPosition(RecyclerView.java:5249)
                  at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5431)
                  at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5392)
                  at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5388)
                  at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2149)
                  at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1533)
                  at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1496)
                  at android.support.v7.widget.LinearLayoutManager.scrollBy(LinearLayoutManager.java:1313)
                  at android.support.v7.widget.LinearLayoutManager.scrollVerticallyBy(LinearLayoutManager.java:1058)
                  at android.support.v7.widget.RecyclerView.scrollByInternal(RecyclerView.java:1680)
                  at android.support.v7.widget.RecyclerView.onTouchEvent(RecyclerView.java:2837)
                  at android.view.View.dispatchTouchEvent(View.java:9302)
                  at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2548)
                  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2241)
                  at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2554)
                  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2255)
                  at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2554)
                  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2255)
                  at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2554)
                  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2255)
                  at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2554)
                  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2255)
                  at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2554)
                  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2255)
                  at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2554)
                  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2255)
                  at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2554)
                  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2255)
                  at com.android.internal.policy.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2403)
                  at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1737)
                  at android.app.Activity.dispatchTouchEvent(Activity.java:2805)
                  at android.support.v7.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:71)
                  at com.android.internal.policy.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2364)
                  at android.view.View.dispatchPointerEvent(View.java:9522)
                  at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4230)
                  at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:4096)
                  at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642)
                  at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3695)
                  at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3661)
                  at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3787)
                  at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3669)
                  at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3844)
                  at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642)
                  at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3695)
                  at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3661)
                  at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3669)
                  at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3642)
                at android.view.ViewRootImpl.deliverInput
Community
  • 1
  • 1
Long Luong
  • 764
  • 2
  • 14
  • 28
  • You keep modifying the list in `eventToList()`. Copy the list for your adapter or don't modify it after setting it – David Medenjak Mar 21 '17 at 10:47
  • make static viewholder – Kiran Benny Joseph Mar 21 '17 at 10:50
  • A shallow guess, but instead of modifying/clearing the eventList outside the adapter, wouldn't it be better to copy the eventList and modify the copy of the eventList. Upon finishing the modifications swap the old data for the new data and notifyDatasetChanged()? It's still a guess tho.. – Bart de Ruijter Mar 21 '17 at 11:00
  • In eventToList() you need (recyclerView.setAdapter(null); eventAdapter = new EventAdapter(getActivity().getApplicationContext(), eventList)) so its fresh otherwise it wont clear – Tasos Mar 21 '17 at 11:15
  • **Using a copy of eventList and swap it for new list** also does not work, because `notifyDataSetChange()` doest not do its job. the recyclerView shows nothing – Long Luong Mar 21 '17 at 11:16
  • @Tasos I did not want to set a new adapter everytime, because it mights take me to _runOutOfMemory_ problem and recyclerView jumps alse everytime to the top (even though i can use onSaveInstanceState). – Long Luong Mar 21 '17 at 11:22
  • 1
    So to clarify, you tried to: first create a new list/copy of eventList. (clear this list if it's a copy). Add new data in this list. override the eventList (e.g. eventList = EventListwithnewdata) in the adapter (since eventList is private in the adapter, through a method). Followed by calling notifyDatasetChanged() to let the adapter know its data has changed. I'm just wanting to make sure since the "Inconsistency detected" together with your data that's being loaded from the server, sounds like there is an x amount of time between the .clear and notify datasetChanged. but it's a quick guess. – Bart de Ruijter Mar 21 '17 at 11:26
  • @Tasos a list of items that im getting from server could be less or more(the problem is that I dont know what items should be deleted or added after every request. So the best solution was, making a new list everytime and notifying adapter) – Long Luong Mar 21 '17 at 11:36
  • 1
    then you need you a new list every 10 secs because in essence that's what you are doing. try what i suggested and clear the adapter every time. – Tasos Mar 21 '17 at 12:03
  • @BartdeRuijter Im going to leave `eventList` there without touching it (neither clear nor add). I create inside the operation `eventToList` a new list calls `EventListwithnewdata` and use the operation `update(EventListwithnewdata)` which I already implemented in adapter. And it seems to be working yet. – Long Luong Mar 21 '17 at 12:19
  • @Tasos Yes I need to create a new list every 10 secs, but no need to clear the adapter. :). many thanks – Long Luong Mar 21 '17 at 12:25
  • If it works, it works! Cheers. – Bart de Ruijter Mar 21 '17 at 12:27

0 Answers0