1

I have the problem that I want to update a nested RecyclerView with dynamically loading data. The outer recyclerView is vertical and the inner recyclerView is horizontal. So, I have created 2 adapters.

The main activity:

public class GroupScreenActivity extends AppCompatActivity {


    private RecyclerView recyclerView;
    private OuterRecyclerViewAdapter adapter;



    // the service connection
    private ServiceConnection connection = new ServiceConnection() {
         ... // code that handles the service connection (not relevant for my question)
        }
    };

    @Override
    protected void onStart(){
        // code that bind the service to the activity (not really relevant for my question)
    }

    @Override
    protected void onStop(){
    // code that unbinds the service from the activity (not really relevant for my question)
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_group_screen);

        recyclerView = (RecyclerView) findViewById(R.id.recycler_View);

        recyclerView.setLayoutManager(new LinearLayoutManager(this));

        updateUI();
    }

    // a Handler that calls a method of a bound service to retrieve the data of interest
    private void updateUI(final String token){

        final Handler handler = new Handler();

        handler.post(new Runnable() {
            @Override
            public void run() {
                if(bound && (mDownloadCliquesService != null)){

                    // holds the list of the statement lists
                    ArrayList<ArrayList<Statement>> myList = mDownloadCliquesService.getDataOfUser();

                    if(adapter == null){
                        // data is passed to the outer recyclerView adapter

                        adapter = new OuterRecyclerViewAdapter(this, myList);
                        recyclerView.setAdapter(adapter);
                    }
                    else{
                        // notify that the data is changed
                        adapter.notifyDataSetChanged();
                    }

                }
                // repeat the whole after 5 seconds
                handler.postDelayed(this, 5000);
            }
        });
    }
}

As you can see: The main activity just retrieves some data from a bound service and passes it to the outer recycler view. The data is a list of lists of type Statement. The number of lists in myList gives the rows of the outer recyclerview and the items in each list will define the number of columns of each inner recyclerview.

The outer recycler view looks like the following:

public class OuterRecyclerViewAdapter extends RecyclerView.Adapter<OuterRecyclerViewAdapter.InnerRecyclerViewHolder> {


    // some instance variables

    public OuterRecyclerViewAdapter( ... ) {
        ...
    }


    @Override
    public InnerRecyclerViewHolder onCreateViewHolder(final ViewGroup parent, int viewType) {

        LayoutInflater inflater = LayoutInflater.from(context);
        View view = inflater.inflate(R.layout.inner_recyclerview_layout, parent, false);

        return new InnerRecyclerViewHolder(view);
    }

    @Override
    public void onBindViewHolder(final InnerRecyclerViewHolder holder, int position) {

        // here, I create the inner recycler view adapter. Do I need to update it too???
        adapter = new InnerRecyclerViewAdapter(context, items, position);

        holder.recyclerView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false));
        holder.recyclerView.setAdapter(adapter);
    }

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

    public class InnerRecyclerViewHolder extends RecyclerView.ViewHolder {

        private RecyclerView recyclerView;
        private Button mAddButton;
        private Button mSendButton;
        private TextView tvCliqueName;
        private ArrayList<Object> mList;


        public InnerRecyclerViewHolder(View itemView) {
            super(itemView);

            // using 'itemView', get a reference to the inner recycler view.
            recyclerView = (RecyclerView) itemView.findViewById(R.id.inner_recyclerView);

            // get a reference to the clique name
            tvCliqueName = (TextView) itemView.findViewById(R.id.cliqueName);

            // get a reference to the send button
            mSendButton = (Button) itemView.findViewById(R.id.send);

            // get a reference to the add button
            mAddButton = (Button) itemView.findViewById(R.id.add);

        }
    }

}

For the sake of brevity, I do not post the code for the inner recyclerview adapter because there is no adapter reference to update. So, after every 5 second the main activity gets fresh data from my bound service and passes it to the outer recyclerview adapter which looks how many lists exist in the nested array list. Each list is then passed to the inner recycler view adapter which then shows the elements of each list. So, my problem is the following: After each update the list is scrolling to the beginning. Let's say I have 5 elements in the first list, and I scroll to the 3rd one, after the update inner recycler view goes to the 1st automatically. Here is a short GIF how the output looks like:

enter image description here

I have checked out the following StackOverflow posts: How to save RecyclerView's scroll position using RecyclerView.State?

Nested Recyclerview scrolls by itself

How to save scroll position of recyclerview in fragment

How to save scroll position of RecyclerView in Android?

But without success. How do I need to update so that the scroll position is not affected ?

Thanks and best regards

ebeninki
  • 638
  • 5
  • 18

1 Answers1

0

Save your horizontal scroll value:

outerRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
    @Override
    public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
        super.onScrollStateChanged(recyclerView, newState);
    }

    @Override
    public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
        //save dx
    }
});

and restore after update: outerRecyclerView.setScrollX(dx)

underoid
  • 369
  • 3
  • 11