load more data into recycleview while scrolling

457 Views Asked by At

First I read the data from server and put it into an ArrayList. Next, I put the ArrayList into an Adapter for a RecyclerView. When the user reaches the end, I want to send a request to server and get data for the RecyclerView. Now, I do it and it works. However, when I add more data, my RecyclerView moves to the first item and I must scroll down to see the new data...I want to add more data to the bottom of the RecyclerView without going back to the top.

This is my method to send the request to the server and fill my ArrayList:

private void getPosts(final Integer page, Integer limit) {
    getPosts(null, page, limit, new RemoteCallback<ResponseBody>() {
        @Override
        public void onSuccess(ResponseBody responseBody) {

            try {
                JSONArray data = new JSONArray(responseBody.string());
                if (data.length() == 0) {
                    Toast.makeText(getApplicationContext(), "Finish", Toast.LENGTH_LONG).show();
                } else {
                    for (int i = 0; i < data.length(); i++) {
                        posts = getPosts_(data);
                    }
                }
            } catch (Exception e) {
            }
            posts2.addAll(posts);
        }

        @Override
        public void onUnauthorized() {
            Log.e("data", "onUnauthorized");
        }

        @Override
        public void onFailed(Throwable throwable) {
            Log.e("data", "onFailed");
        }
    });
}

And here is my Activity:

public class MainActivity2 extends AppCompatActivity {
    private static int ITEM_REQUEST_INITIAL_OFFSET = 1;
    private static final int ITEM_REQUEST_LIMIT = 10;
    private APIService mAPIService;
    ProgressBar progressBar;
    RecyclerView recyclerView;
    AdapterContent item2RecyclerAdapter;
    private int mLoadedItems = 0;
    public static List<Post> posts = new ArrayList<Post>();
    List<Post> posts2 = new ArrayList<Post>();

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

        mAPIService = ApiUtils.getAPIService();
        progressBar = findViewById(R.id.item_progress_bar);
        recyclerView = findViewById(R.id.recycler_view);
        getPosts(ITEM_REQUEST_INITIAL_OFFSET, ITEM_REQUEST_LIMIT);

        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(MainActivity2.this);
        linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(linearLayoutManager);
        recyclerView.addItemDecoration(new DividerItemDecoration(MainActivity2.this, DividerItemDecoration.VERTICAL));
recyclerView.setAdapter(adapter) item2RecyclerAdapter = new AdapterContent(posts2);
        recyclerView.addOnScrollListener(new EndlessRecyclerOnScrollListener() {
            @Override
            public void onLoadMore() {
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        getPosts(ITEM_REQUEST_INITIAL_OFFSET, 10);
                    }
                }, 1500);
                ITEM_REQUEST_INITIAL_OFFSET++;
            }
        });
    }

And here is my Adapter content:

public class AdapterContent extends RecyclerView.Adapter<AdapterContent.SecondCollectionViewHolder> {
    private List<Post> posts;
    private Context context;
    private RemoteCallback<ResponseBody>remoteCallback;
    public SharedPreferences sp;
    public boolean state;


    public AdapterContent(List<Post> postList) {
        this.context = context;
        this.posts = postList;
        this.remoteCallback= remoteCallback;
    }

    @Override
    public AdapterContent.SecondCollectionViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View secondCollectionView = LayoutInflater.from(parent.getContext()).inflate(R.layout.row, parent, false);
        return new SecondCollectionViewHolder(secondCollectionView);
    }

    @Override
    public long getItemId(int position) {
        return super.getItemId(position);
    }

    @Override
    public void onBindViewHolder(final AdapterContent.SecondCollectionViewHolder secondHolder, final int position) {
        final Post post = posts.get(position);

        secondHolder.txt_postTitle.setText(post.getTitle());
        Log.i("mhs",post.getTitle());
    }
    public void add(Post r) {
        circleList.add(r);
        notifyItemInserted(posts.size() - 1);
    }

    public void addAll(ArrayList<Post> moveResults) {
        for (Post result : moveResults) {
            add(result);
        }
    }

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

    public class SecondCollectionViewHolder extends RecyclerView.ViewHolder {

        public TextView txt_postTitle;
        public RelativeLayout relativeLayout;

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

            txt_postTitle = (TextView) itemView.findViewById(R.id.txt_postTitle);    
        }
    }
}

My question is how can I add data without going to first row in the RecyclerView?

1

There are 1 best solutions below

0
Alireza Tizfahm Fard On

Lazy loading implementation with custom library or helper when load more received at the end of list

abstract class EndlessListener(private val carouselLayoutManager: CarouselLayoutManager) :
    RecyclerView.OnScrollListener() {

    private val visibleThreshold = 5
    private var currentPage = 0
    private var previousTotalItemCount = 0
    private var loading = true
    private var startingPageIndex = 0

    fun getLastVisibleItem(lastVisibleItemPositions: IntArray): Int {
        var maxSize = 0
        for (i in lastVisibleItemPositions.indices) {
            if (i == 0) {
                maxSize = lastVisibleItemPositions[i]
            } else if (lastVisibleItemPositions[i] > maxSize) {
                maxSize = lastVisibleItemPositions[i]
            }
        }
        return maxSize
    }

    override fun onScrolled(view: RecyclerView, dx: Int, dy: Int) {
        val lastVisibleItemPosition = (carouselLayoutManager as LinearLayoutManager).findLastVisibleItemPosition()
        val totalItemCount = carouselLayoutManager.itemCount

        if (totalItemCount < previousTotalItemCount) {
            currentPage = startingPageIndex
            previousTotalItemCount = totalItemCount
            if (totalItemCount == 0) {
                loading = true
            }
        }

        if (loading && totalItemCount > previousTotalItemCount) {
            loading = false
            previousTotalItemCount = totalItemCount
        }

        if (!loading && lastVisibleItemPosition + visibleThreshold > totalItemCount) {
            currentPage++
            onLoadMore(currentPage, totalItemCount, view)
            loading = true
        }
    }

    fun resetState() {
        this.currentPage = this.startingPageIndex
        this.previousTotalItemCount = 0
        this.loading = true
    }

    abstract fun onLoadMore(page: Int, totalItemsCount: Int, view: RecyclerView)

}

And add a listener for change scroll position

 recycelerView.addOnScrollListener(object : EndlessListener(layoutManager) {
                override fun onLoadMore(page: Int, totalItemsCount: Int, view: RecyclerView) {

                }
            })