0

I have a RecyclerView fetching data from an API. I am using Volley. I am fetching data in batches of 20 items. I wish to set the scroll position using Linear Layout Manager myLLM.scrollToPositionWithOffset(x,y) so that when next batch of data is fetched the scroll position which currently resets to top is retained at the last item of previous batch.

For this i need to add the following line of code at the place shown in the code below.

myLLM.scrollToPositionWithOffset(y,0);

But i am not able to do so. Please guide me on how achieve this.

public class ActivityItems extends AppCompatActivity {

private RecyclerView myRvItems;
private ItemsAdapter myItemsAdapter;
private ArrayList<ItemsModel> myItemsFeedList;
private RequestQueue myRequestQueue;
private ProgressBar itemsProgressBar;
Boolean isScrolling = false;
int currentItems, totalItems, scrolledOutItems, x = 0, y = (x + 20);

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

    getSupportActionBar().setTitle("Inventory Items");
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

    myRvItems = findViewById(R.id.rvItems);
    itemsProgressBar = findViewById(R.id.pbItems);

    final LinearLayoutManager myLLM = new LinearLayoutManager(this);
    myRvItems.setLayoutManager(myLLM);

    myItemsFeedList = new ArrayList<>();
    myRequestQueue = Volley.newRequestQueue(this);

    parseJSON();

    myRvItems.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
            if(newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL){
                isScrolling = true;
            }
        }

        @Override
        public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            currentItems = myLLM.getChildCount();
            totalItems = myLLM.getItemCount();
            scrolledOutItems = myLLM.findFirstVisibleItemPosition();

            if(isScrolling && (currentItems + scrolledOutItems == totalItems)){
                isScrolling = false;
                parseJSON();
                myLLM.scrollToPositionWithOffset(4, 20);
            }
        }
    });

}

private void parseJSON() {

    itemsProgressBar.setVisibility(View.VISIBLE);
    String url = "http://restapis.xyv.com/api/list";

    JsonObjectRequest myRequest = new JsonObjectRequest(Request.Method.GET, url, null,
            new Response.Listener<JSONObject>() {
                @Override
                public void onResponse(JSONObject response) {

                    try {
                        JSONArray myJSONArray = response.getJSONArray("Data");

                        for (int i = x; i < y && i < myJSONArray.length(); i++){

                            JSONObject myData = myJSONArray.getJSONObject(i);

                            String itemID = myData.getString("ItemID");
                            String itemName = myData.getString("ItemName");
                            String itemRackNo = myData.getString("RackNo");

                            myItemsFeedList.add(new ItemsModel(itemID,itemName,itemRackNo));

    **//   I WANT TO SET THE SCROLL POSITION HERE BUT THIS NOT WORKING**
    **//   myLLM.scrollToPositionWithOffset(y,0);**

                        }

                        myItemsAdapter = new ItemsAdapter(myItemsFeedList,ActivityItems.this );
                        myRvItems.setAdapter(myItemsAdapter);
                        itemsProgressBar.setVisibility(View.GONE);

                    } catch (JSONException e) {
                        e.printStackTrace();
                    }

                }
            }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            error.printStackTrace();
        }
    });

    myRequestQueue.add(myRequest);

}

@Override
public boolean onSupportNavigateUp() {
    onBackPressed();
    return super.onSupportNavigateUp();
}

}

Saqib
  • 377
  • 4
  • 7
  • 1
    You can't scroll to position without having set the adapter first. Plus, you're setting the adapter in a method which might be called multiple times. This is not good practice. Set your adapter first, even if your list is empty. Update your list when you get the data. Then call adapter.notifydatasetchanged() method. You can then scroll to the last position. Let me know if this answers your question or if I have to put an answer – mmmcho May 24 '20 at 23:03
  • @mmmcho Thanks a lot. Did as you said, "Set your adapter first, even if your list is empty. Update your list when you get the data. Then call adapter.notifyDataSetChanged() method." Now the RecyclerVeiw doesnot reset to the top. So no need to set the scroll position as well. Good practice worked great. Thanks again. – Saqib May 25 '20 at 09:45

1 Answers1

0

Following the advice from @mmmcho the issue was solved. "Set your adapter first, even if your list is empty. Update your list when you get the data. Then call adapter.notifydatasetchanged() method."

There is also a crude way of pagination implemented. So if someone is looking for easiest RecyclerView pagination, he can also follow the code.(Just have your api data sorted by date and it will work best.)

The code now looks like follows:

public class ActivityItems extends AppCompatActivity {

private RecyclerView myRvItems;
private ItemsAdapter myItemsAdapter;
private ArrayList<ItemsModel> myItemsFeedList;
private RequestQueue myRequestQueue;
private ProgressBar itemsProgressBar;
Boolean isScrolling = false;
int currentItems, totalItems, scrolledOutItems, fetchSize = 6 , x = 0, y = (x + fetchSize);

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

    getSupportActionBar().setTitle("Inventory Items");
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

    myRvItems = findViewById(R.id.rvItems);
    itemsProgressBar = findViewById(R.id.pbItems);

    final LinearLayoutManager myLLM = new LinearLayoutManager(this);
    myRvItems.setLayoutManager(myLLM);

    myItemsFeedList = new ArrayList<>();
    myItemsAdapter = new ItemsAdapter(myItemsFeedList,ActivityItems.this );
    myRvItems.setAdapter(myItemsAdapter);

    myRequestQueue = Volley.newRequestQueue(this);

    parseJSON();


    myRvItems.addOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);
            if(newState == AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL){
                isScrolling = true;
            }
        }

        @Override
        public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
            currentItems = myLLM.getChildCount();
            totalItems = myLLM.getItemCount();
            scrolledOutItems = myLLM.findFirstVisibleItemPosition();

            if(isScrolling && (currentItems + scrolledOutItems == totalItems)){
                isScrolling = false;
                y = x + fetchSize;
                parseJSON();

            }
        }
    });

}

private void parseJSON() {

    itemsProgressBar.setVisibility(View.VISIBLE);
    String url = "http://restapis.xyn.com/api/list";

    JsonObjectRequest myRequest = new JsonObjectRequest(Request.Method.GET, url, null,
            new Response.Listener<JSONObject>() {
                @Override
                public void onResponse(JSONObject response) {

                    try {
                        JSONArray myJSONArray = response.getJSONArray("Data");

                        for (int i = x; i < y && i < myJSONArray.length(); i++){

                            JSONObject myData = myJSONArray.getJSONObject(i);

                            String itemID = myData.getString("ItemID");
                            String itemName = myData.getString("ItemName");
                            String itemRackNo = myData.getString("RackNo");

                            myItemsFeedList.add(new ItemsModel(itemID,itemName,itemRackNo));
                            x = x+1;
                        }

                        myItemsAdapter.notifyDataSetChanged();
                        itemsProgressBar.setVisibility(View.GONE);

                    } catch (JSONException e) {
                        e.printStackTrace();
                    }

                }
            }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            error.printStackTrace();
        }
    });

    myRequestQueue.add(myRequest);

}

@Override
public boolean onSupportNavigateUp() {
    onBackPressed();
    return super.onSupportNavigateUp();
}}
Saqib
  • 377
  • 4
  • 7