Preface:
In the process of project development, we usually have the demand of "paging load". Paging load is to display data in the form of list. On the premise of having a network, we can manually obtain more data through pull-down refresh. When there is no more data, we will be reminded that we do not have more data.
Knowledge points used:
- Retrofit to implement network request
- Recyclerview display list information
- Swiperefreshlayout implements pull-down refresh and pull-up loading more
- Picasso load picture
Implementation code
1. Configure gradle dependency
//retrofit compile 'com.squareup.retrofit2:retrofit:2.0.2' compile 'com.squareup.retrofit2:converter-gson:2.0.2' //recyclerview compile 'com.android.support:recyclerview-v7:25.0.1' //picasso compile 'com.squareup.picasso:picasso:2.3.2'
2. Add SwipyRefreshLayout to layout file
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:my="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#FFECECEB" android:orientation="vertical"> <uk.co.common.ui.pull.SwipyRefreshLayout android:id="@+id/refreshLayout" android:layout_width="match_parent" android:layout_height="match_parent" my:direction="both"> <!--Solve RecyclerView And TextView Control conflict--> <android.support.v4.widget.NestedScrollView android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <android.support.v7.widget.RecyclerView android:id="@+id/rv_offer_personal_loans" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_marginTop="10dp" android:divider="#FFFFFFFD" /> <TextView android:id="@+id/tv_bottom_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_marginTop="10dp" android:text="I am bottom text." android:textColor="#384f6f" android:textSize="14sp" android:visibility="gone" /> </LinearLayout> </android.support.v4.widget.NestedScrollView> </uk.co.common.ui.pull.SwipyRefreshLayout> </LinearLayout>
3. Adapter code
public class OfferLoansRVAdapter extends RecyclerView.Adapter<OfferLoansRVAdapter.ViewHolder> implements View.OnClickListener { public List<Offer_personal_loans.LoansBean> LoansBeens; public Context context; public OfferLoansRVAdapter(Context context, List<Offer_personal_loans.LoansBean> loansBeans) { super(); this.context = context; this.LoansBeens = loansBeans; } //Declare the OnRecyclerViewListener object private OfferLoansRVAdapter.OnRecyclerViewListener mOnRecyclerViewListener = null; @Override public void onClick(View v) { if (mOnRecyclerViewListener != null) { mOnRecyclerViewListener.onItemClick(v, (int) v.getTag()); } } //Define the onrecyclerviewlistener interface public interface OnRecyclerViewListener { void onItemClick(View view, int position); } //Set the method the listener uses to pass data to the interface object defined above public void setOnItemClickListener(OfferLoansRVAdapter.OnRecyclerViewListener listener) { this.mOnRecyclerViewListener = listener; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { //R. Layout.common'loan'item: the layout file of the item View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.common_loan_item, parent, false); OfferLoansRVAdapter.ViewHolder vh = new OfferLoansRVAdapter.ViewHolder(view); view.setOnClickListener(this); return vh; } @Override public void onBindViewHolder(ViewHolder holder, final int position) { RecyclerView.ViewHolder viewHolder = holder; try { String logo_url = LoansBeens.get(position).getLogo_url(); Picasso.with(Global.mContext).load(logo_url).into(holder.imgLoanLogo); ... holder.imgLoanCheck.setVisibility(View.VISIBLE); //Save the position in the tag of the itemView to implement the click event holder.itemView.setTag(position); } catch (Exception e) { } } /* *This is an important method to add List data when paging data */ public void addItem(List<Offer_personal_loans.LoansBean> loansBeans) { try { for (Offer_personal_loans.LoansBean loansBean : loansBeans) LoansBeens.add(loansBean); } catch (ConcurrentModificationException e) { e.printStackTrace(); } } @Override public int getItemCount() { return LoansBeens == null ? 0 : LoansBeens.size(); } public Offer_personal_loans.LoansBean getItem(int position) { return LoansBeens.get(position); } public class ViewHolder extends RecyclerView.ViewHolder { private ImageView imgLoanLogo; ... public ViewHolder(View view) { super(view); imgLoanLogo = (ImageView) view.findViewById(R.id.img_loan_logo); ... } } }
4. Code implemented in Fragment
public class OfferPersonalLoansFragment extends BaseFragment implements SwipyRefreshLayout.OnRefreshListener { private SwipyRefreshLayout refreshLayout; private RecyclerView rvOfferPersonalLoans; private Offer_personal_loans offerPersonalLoans; private List<Offer_personal_loans.LoansBean> personalLoansBeen; private List<List<Offer_personal_loans.LoansBean>> offerPersonalLoansList; private OfferLoansRVAdapter offerPersonalLoansRVAdapter; private TextView tvBottomText; //Presenter private CommonPresenter commonPresenter; //Offset private int offset = 0; //Restriction number private int limit = 5; @Override public int getLayoutRes() { return R.layout.offer_personal_loans; } @Override public void initView() { refreshLayout = (SwipyRefreshLayout) findView(R.id.refreshLayout); refreshLayout.setOnRefreshListener(this); rvOfferPersonalLoans = (RecyclerView) findView(R.id.rv_offer_personal_loans); rvOfferPersonalLoans.setLayoutManager(new LinearLayoutManager(getActivity())); tvBottomText = (TextView) findView(R.id.tv_bottom_text); } @Override public void initListener() { } @Override public void initData() { //Network request data showProgressDialog("", "Please wait..."); commonPresenter = new CommonPresenter(this); commonPresenter.getOfferPersonalLoans(uuid, offset * limit, limit); } } @Override public void onClick(View v, int id) { } /* *Method of invocation after network request is successful */ @Override public void onHttpSuccess(int reqType, Message msg) { if (reqType == IHttpService.HTTP_GET_OFFER_PERSONAL_LOANS) { hideProgressDialog(); offerPersonalLoans = (Offer_personal_loans) msg.obj; try { personalLoansBeen = offerPersonalLoans.getLoans(); offerPersonalLoansList = new ArrayList<>(); offerPersonalLoansList.add(personalLoansBeen); } catch (Exception e) { e.printStackTrace(); } initLoanRecyclerView(); tvBottomText.setVisibility(View.VISIBLE); } } private void initLoanRecyclerView() { if (offerPersonalLoansRVAdapter == null) {//Sentence blank offerPersonalLoansRVAdapter = new OfferLoansRVAdapter(getActivity(), personalLoansBeen); rvOfferPersonalLoans.setAdapter(offerPersonalLoansRVAdapter); } else { //Before loading data, when manually refreshing / paging loading data, this is to add List data offerPersonalLoansRVAdapter.addItem(personalLoansBeen); offerPersonalLoansRVAdapter.notifyDataSetChanged(); } refreshLayout.setRefreshing(false);//Remember to add this sentence //Unified handling of click events offerPersonalLoansRVAdapter.setOnItemClickListener(new OfferLoansRVAdapter.OnRecyclerViewListener() { @Override public void onItemClick(View view, int position) { ... } }); } /* *Pull up refresh, request interface */ @Override public void onRefresh(int index) { commonPresenter = new CommonPresenter(this); commonPresenter.getOfferPersonalLoans(uuid, offset * limit, limit); } /* *Paging load, request interface */ @Override public void onLoad(int index) { String uuid = SharedPreUtil.getString(Global.mContext, "membership_uuid", ""); if (!TextUtils.isEmpty(uuid)) { commonPresenter = new CommonPresenter(this); offset++;//Offset + 1 per interface request (designed according to interface) commonPresenter.getOfferPersonalLoans(uuid, offset * limit, limit); } } /* *Method of calling after failure of network request */ @Override public void onHttpError(int reqType, ArrayList<String> error) { if (reqType == IHttpService.HTTP_GET_OFFER_PERSONAL_LOANS) { hideProgressDialog(); } } /* *Method called by network timeout */ @Override public void onHttpFailure(int reqType, String error) { if (reqType == IHttpService.HTTP_GET_OFFER_PERSONAL_LOANS) { hideProgressDialog(); } } /* *Method called by server error */ @Override public void onServerError(int reqType) { if (reqType == IHttpService.HTTP_GET_OFFER_PERSONAL_LOANS) { hideProgressDialog(); } } }
5. Operation rendering:
6. Summary: page by page loading is to load data page by page. When there is no more data to load when sliding to the bottom, we can manually call the interface and refresh RecyclerView. The pull-up function cannot be used. Only after the pull-down refresh, the data can be loaded again. In this way, not only the burden of the server can be reduced, but also the user can save traffic, so as to improve the user experience.