title: RecyclerView Endless Scrolling with RxJava
body: <p>I want to implement <strong>Endless Scrolling</strong> functionality on RecyclerView using RxJava.</p>
  
  <p><strong>What I want:</strong> I want to fetch first 10 data from API call and display it in RecyclerView. After user scrolled down these 10 data, I want to make another API call and pull another 10 data. Again when user scrolls down after these latest 10 data, I have to make API call for another 10 data. This will continues until API call gives all the data.</p>
  
  <p>I tried with <strong>take</strong> operator but not getting desired result. I searched for different operators but not getting single operator or any combination of operator to achieve this. Any help will be appreciated.</p>
  
  <p>My code is like below.</p>
  
  <p><strong>SalesDashboardActivity.java</strong></p>
  
  <pre><code>    public class SalesDashboardActivity2 extends BaseActivity implements SalesDashboardView {
  
      List&lt;DashboardStatusBean&gt; inProgressList = new ArrayList&lt;&gt;();
  
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_sales_dashboard2);
          ButterKnife.bind(this);
          setSupportActionBar(mToolbar);
          mSalesDashboardPresenter.attachView(this);
          getDashboardData();
      }
  
      private void getDashboardData() {
  
          SearchLoansInput searchLoansInput = new SearchLoansInput();
          searchLoansInput.setUserName(sessionManager.getMobileNumber());
  
          if (Util.isInternetConnection(this)) {
              mSalesDashboardPresenter.handleSalesInquiryRequest(searchLoansInput);
          } else {
              displayToastMessage("Internet is not available! Check your internet connection.");
          }
      }
  
      @Override
      public void handleSalesInquiryResponse(SearchLoansOutput searchLoansOutputData) {
  
          if (searchLoansOutputData.isSuccess()) {
  
              Util.SALES_IN_PROGRESS_LIST.clear();
  
              for (int i = 0; i &lt; searchLoansOutputData.getLoanDetailList().size(); i++) {
                  DashboardStatusBean dashboardStatusBean = new DashboardStatusBean();
                  SimpleDateFormat sdf = new SimpleDateFormat("dd MMM yyyy");
                  String approveDate = null;
                  String createdDate = null;
  
                  if (searchLoansOutputData.getLoanDetailList().get(i).getCreatedDate() != null) {
                      createdDate = String.valueOf(sdf.format(searchLoansOutputData.getLoanDetailList().get(i).getCreatedDate()));
                  }
                  if (searchLoansOutputData.getLoanDetailList().get(i).getApprovedDate() != null) {
                      approveDate = String.valueOf(sdf.format(searchLoansOutputData.getLoanDetailList().get(i).getApprovedDate()));
                  }
  
                  String loanNumber = searchLoansOutputData.getLoanDetailList().get(i).getLoanNumber();
                  String firstName = searchLoansOutputData.getLoanDetailList().get(i).getFirstName();
                  String lastName = searchLoansOutputData.getLoanDetailList().get(i).getLastName();
                  String mobileNumber = searchLoansOutputData.getLoanDetailList().get(i).getMobileNumber();
                  String status = searchLoansOutputData.getLoanDetailList().get(i).getStatus().getDisplayName();
                  String loanAmount = String.valueOf(searchLoansOutputData.getLoanDetailList().get(i).getLoanAmount().setScale(0, BigDecimal.ROUND_UP));
                  String loanAppId = searchLoansOutputData.getLoanDetailList().get(i).getId();
                  BigDecimal productAmount = searchLoansOutputData.getLoanDetailList().get(i).getTotalProductAmount();
                  BigDecimal downPayment = searchLoansOutputData.getLoanDetailList().get(i).getDownPayment();
                  BigDecimal processingFee = searchLoansOutputData.getLoanDetailList().get(i).getProcessingFee();
                  String tenure = searchLoansOutputData.getLoanDetailList().get(i).getDesiredItemPaybackTenure();
                  String sourceAcquisition = searchLoansOutputData.getLoanDetailList().get(i).getSourceAcquisition();
                  List&lt;SingleDocumentOuput&gt; documentUpdatedList = searchLoansOutputData.getLoanDetailList().get(i).getDocOutputList();
  
                  dashboardStatusBean.setCreatedDate(createdDate);
                  dashboardStatusBean.setApproveDate(approveDate);
                  dashboardStatusBean.setLoanNumber(loanNumber);
                  dashboardStatusBean.setFirstName(firstName);
                  dashboardStatusBean.setLastName(lastName);
                  dashboardStatusBean.setMobileNumber(mobileNumber);
                  dashboardStatusBean.setStatus(status);
                  dashboardStatusBean.setLoanAppId(loanAppId);
                  dashboardStatusBean.setProductAmount(productAmount);
                  dashboardStatusBean.setDownPayment(downPayment);
                  dashboardStatusBean.setProcessingFee(processingFee);
                  dashboardStatusBean.setTenure(tenure);
                  dashboardStatusBean.setLoanAmount(loanAmount);
                  dashboardStatusBean.setDocumentUpdatedList(documentUpdatedList);
  
                  if (status.equals(LoanApplicationStatus.STILL_FILLING.getDisplayName()) ||
                          status.equals(LoanApplicationStatus.ONBOARDIN_IN_PROG.getDisplayName()) ||
                          status.equals(LoanApplicationStatus.INITIATED.getDisplayName()) ||
                          status.equals(LoanApplicationStatus.ADDITIONAL_DATA_REQ.getDisplayName()) ||
                          status.equals(LoanApplicationStatus.UPLOAD_IN_PROG.getDisplayName()) ||
                          status.equals(LoanApplicationStatus.VERIFIED.getDisplayName()) ||
                          status.equals(LoanApplicationStatus.LEAD.getDisplayName())) {
                      inProgressList.add(dashboardStatusBean);
                  }
  
                  Util.SALES_IN_PROGRESS_LIST = inProgressList;
              }
  
          } else {
              displayMessage(searchLoansOutputData.getErrorCode(), searchLoansOutputData.getErrorMessage());
          }
      }
  }
  </code></pre>
  
  <p><strong>SalesLoginDashboardPresenter.java</strong></p>
  
  <pre><code>    public class SalesLoginDashboardPresenter implements Presenter {
  
      private SalesDashboardView mView;
      private final SalesLoginInquiryUseCase mSalesInquiryUseCase;
  
      @Inject
      public SalesLoginDashboardPresenter(SalesLoginInquiryUseCase salesLoginInquiryUseCase) {
          mSalesInquiryUseCase = salesLoginInquiryUseCase;
      }
  
      @Override
      public void attachView(View v) {
          mView = (SalesDashboardView) v;
      }
  
      public void handleSalesInquiryRequest(SearchLoansInput searchLoansInput) {
          mView.displayLoadingScreen();
          mSalesInquiryUseCase.setSalesLoginInquiryBody(searchLoansInput);
          mSalesInquiryUseCase.execute()
                  .subscribe(this::onSalesInquiryReceived, this::onSalesInquiryError);
      }
  
      private void onSalesInquiryError(Throwable throwable) {
          mView.hideLoadingScreen();
          mView.displayErrorMessage("Error fetching data");
          throwable.printStackTrace();
      }
  
      private void onSalesInquiryReceived(SearchLoansOutput searchLoansOutput) {
          mView.hideLoadingScreen();
          mView.handleSalesInquiryResponse(searchLoansOutput);
      }
  }
  </code></pre>
  
  <p><strong>SalesLoginInquiryUseCase.java</strong></p>
  
  <pre><code>    public class SalesLoginInquiryUseCase extends Usecase&lt;SearchLoansOutput&gt; {
  
      private final MerchantRepository mRepository;
      private final Scheduler mUiThread;
      private final Scheduler mExecutorThread;
      private SearchLoansInput mSearchLoansInput;
      private String mCookie;
  
      @Inject
      public SalesLoginInquiryUseCase(
              MerchantRepository repository,
              @Named("ui_thread") Scheduler uiThread,
              @Named("executor_thread") Scheduler executorThread) {
  
          mRepository = repository;
          mUiThread = uiThread;
          mExecutorThread = executorThread;
      }
  
      public void setSalesLoginInquiryBody(SearchLoansInput searchLoansInput){
          mSearchLoansInput = searchLoansInput;
      }
  
      @Override
      public Observable&lt;SearchLoansOutput&gt; buildObservable() {
          return mRepository.postSalesLoginDetailsInquiryBody(mSearchLoansInput)
                  .observeOn(mUiThread)
                  .subscribeOn(mExecutorThread);
      }
  }
  </code></pre>