今天完成的任務:實現筆記展示界面的上拉刷新和下拉加載
遇到的困難:
1、加載recyclerview時偶爾出現刷新不成功的情況 原因:recyclerview中數據緩存的問題
2、上拉加載和下拉刷新衝突的過程 原因:主要是list集合中數據沒有刷新(list集合中remove()方法的原理不清楚,這裏採用的是模擬數據,注:使用remove()方法刪除應從末尾開始刪除,如果從頭開始刪除會比較麻煩)
3、模擬數據過多時,主線程承擔壓力較大,可能會出現延遲加載,還要考慮訪問遠程數據庫用戶網絡不佳的狀況。
解決思路:
1、數據變更時提示adpater中數據發生改變即可。(方法:adapter.notifyDataSetChanged())
2、上拉加載一共有刷新和到底兩個狀態,首先將到底提示屬性設置爲隱藏,remove方法從後往前刪除,或更新。
3、新建一個子線程,由子線程完成相關查詢操作,主線程只負責結果的展示,這裏避免數據過多可以採用一次只查詢十條數據。
明日的任務:
連接遠程數據庫,進行簡單的登錄註冊驗證。
附上代碼:
底部提示信息佈局,下拉刷新谷歌提供了SwipeRefreshLayout組件,直接重寫方法即可,上拉加載需要自己編寫。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:orientation="horizontal"> <ProgressBar android:id="@+id/pb_loading" android:layout_width="wrap_content" android:layout_height="wrap_content" android:indeterminateDrawable="@drawable/progressbar_refresh" > </ProgressBar> <TextView android:id="@+id/tv_loading" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="15dp" android:text="正在加載中..." android:textColor="#4D6ABC" android:textSize="16sp" > </TextView> <LinearLayout android:id="@+id/ll_end" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:gravity="center" android:orientation="horizontal" > <View android:layout_width="0dp" android:layout_height="1dp" android:layout_weight="1" android:alpha="0.5" android:background="#4DB6AC" > </View> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="我是有底線的" android:textColor="#4DB9AC" android:textSize="16sp"> </TextView> <View android:layout_width="0dp" android:layout_height="1dp" android:layout_weight="1" android:alpha="0.5" android:background="#4DB6AC" > </View> </LinearLayout> </LinearLayout>
上拉加載更多需要更改Adapter
package com.itheima.cloudnotes.adapter; import android.content.Context; import android.content.Intent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import com.itheima.cloudnotes.Activity.Detail; import com.itheima.cloudnotes.R; import com.itheima.cloudnotes.enity.Note; import java.util.List; public class NoteAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private List<Note> mNoteList; private Context mContext; //普通佈局 private final int TYPE_ITEM = 1; //腳佈局 private final int TYPE_FOOTER=2; //當前爲加載狀態,默認爲加載完成 private int loadState=2; //正在加載 public final int LOADING=1; //加載完成 public final int LOADING_COMPLETE=2; //加載到底 public final int LOADING_END=3; @Override public int getItemViewType(int position) { //最後一個item設置爲FootView if(position+1==getItemCount()){ return TYPE_FOOTER; }else { return TYPE_ITEM; } } @NonNull @Override //onCreateViewHolder負責承載每個子項的佈局。它有兩個參數,其中一個是 int viewType; public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { mContext=parent.getContext(); //進行判斷顯示類型,來創造返回不同的View if (viewType==TYPE_ITEM) { View view=LayoutInflater.from(parent.getContext()).inflate(R.layout.recyclerview_item,parent,false); return new RecyclerViewHolder(view); } else if(viewType==TYPE_FOOTER) { View view=LayoutInflater.from(parent.getContext()).inflate(R.layout.refresh_footer,parent,false); return new FootViewHolder(view); } return null; } //onBindViewHolder負責將每個子項holder綁定數據,倆參數分別是RecyclerView.ViewHolder holder, int position; @Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { if(holder instanceof RecyclerViewHolder) { RecyclerViewHolder recyclerViewHolder = (RecyclerViewHolder) holder; final Note note=mNoteList.get(position); recyclerViewHolder.icon.setImageResource(note.getIcon()); recyclerViewHolder.tv_writer_name.setText(note.getWriter_name()); recyclerViewHolder.tv_course.setText(note.getCourse()); recyclerViewHolder.collect.setImageResource(note.getCollect()); recyclerViewHolder.tv_title.setText(note.getTitle()); recyclerViewHolder.tv_date.setText(note.getDate()); recyclerViewHolder.tv_title.setOnClickListener(new View.OnClickListener( ) { @Override public void onClick(View v) { Intent intent=new Intent(mContext,Detail.class); intent.putExtra("writer_name",note.getWriter_name()); mContext.startActivity(intent); } }); recyclerViewHolder.collect.setOnClickListener(new View.OnClickListener( ) { @Override public void onClick(View v) { } }); } else if(holder instanceof FootViewHolder) { FootViewHolder footViewHolder = (FootViewHolder) holder; switch (loadState) { case LOADING: // 正在加載 footViewHolder.pbLoading.setVisibility(View.VISIBLE); footViewHolder.tvLoading.setVisibility(View.VISIBLE); footViewHolder.llEnd.setVisibility(View.GONE); break; case LOADING_COMPLETE: // 加載完成 footViewHolder.pbLoading.setVisibility(View.INVISIBLE); footViewHolder.tvLoading.setVisibility(View.INVISIBLE); footViewHolder.llEnd.setVisibility(View.GONE); break; case LOADING_END: // 加載到底 footViewHolder.pbLoading.setVisibility(View.GONE); footViewHolder.tvLoading.setVisibility(View.GONE); footViewHolder.llEnd.setVisibility(View.VISIBLE); break; default: break; } } } @Override public int getItemCount() { return mNoteList.size()+1; } public NoteAdapter(List<Note> mNoteList) { this.mNoteList = mNoteList; } private class RecyclerViewHolder extends RecyclerView.ViewHolder{ View NoteView; ImageView icon; TextView tv_writer_name; TextView tv_course; ImageView collect; TextView tv_title; TextView tv_date; public RecyclerViewHolder(@NonNull View itemView) { super(itemView); NoteView=itemView; icon=itemView.findViewById(R.id.icon); tv_writer_name=itemView.findViewById(R.id.writer_name); tv_course=itemView.findViewById(R.id.course); collect=itemView.findViewById(R.id.collect); tv_title=itemView.findViewById(R.id.title); tv_date=itemView.findViewById(R.id.date); } } private class FootViewHolder extends RecyclerView.ViewHolder { ProgressBar pbLoading; TextView tvLoading; LinearLayout llEnd; public FootViewHolder(@NonNull View itemView) { super(itemView); pbLoading = (ProgressBar) itemView.findViewById(R.id.pb_loading); tvLoading = (TextView) itemView.findViewById(R.id.tv_loading); llEnd = (LinearLayout) itemView.findViewById(R.id.ll_end); } } //設置上拉加載狀態 @param loadState 0.正在加載 1.加載完成 2.加載到底 public void setLoadState(int loadState) { this.loadState = loadState; notifyDataSetChanged(); } }
滑動監聽
package com.itheima.cloudnotes.listener; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; public abstract class EndlessRecyclerOnScrollListener extends RecyclerView.OnScrollListener { //用來標記是否正在向上滑動 private boolean isSlidingUpward = false; @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); LinearLayoutManager manager = (LinearLayoutManager) recyclerView.getLayoutManager(); // 當不滑動時 if (newState == RecyclerView.SCROLL_STATE_IDLE) { //獲取最後一個完全顯示的itemPosition int lastItemPosition = manager.findLastCompletelyVisibleItemPosition(); int itemCount = manager.getItemCount(); // 判斷是否滑動到了最後一個item,並且是向上滑動 if (lastItemPosition == (itemCount - 1) && isSlidingUpward) { //加載更多 onLoadMore(); } } } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); // 大於0表示正在向上滑動,小於等於0表示停止或向下滑動 isSlidingUpward = dy > 0; } /** * 加載更多回調 */ public abstract void onLoadMore(); }
主活動中上拉加載和下拉刷新
public void upMore() { // 設置加載更多監聽 recyclerView.addOnScrollListener(new EndlessRecyclerOnScrollListener() { @Override public void onLoadMore() { noteAdapter.setLoadState(noteAdapter.LOADING); if (noteList.size()!=20) { // 模擬獲取網絡數據,延時1s new Timer().schedule(new TimerTask() { @Override public void run() { runOnUiThread(new Runnable() { @Override public void run() { initNotes(); noteAdapter.setLoadState(noteAdapter.LOADING_COMPLETE); } }); } }, 1000); } else { // 顯示加載到底的提示 noteAdapter.setLoadState(noteAdapter.LOADING_END); } } }); } @SuppressLint("ResourceAsColor") public void downFresh() { srl=findViewById(R.id.swipe_refresh_layout);//獲取SwipeRefreshLayout實例 srl.setColorSchemeColors(R.color.colorPrimary);//設置刷新進度顏色 srl.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener( ) { @Override public void onRefresh() { new Thread(new Runnable( ) { @Override public void run() { try { Thread.sleep(100); //爲了體現刷新效果,這裏休眠了線程 } catch (InterruptedException e) { e.printStackTrace( ); } //切回主線程 runOnUiThread(new Runnable( ) { @Override public void run() { initNotes1(); //重新刷新數據 noteAdapter.notifyDataSetChanged();//通知數據已發生變化 srl.setRefreshing(false);//當刷新結束時隱藏刷新條 } }); } }).start(); } }); }
下拉提示信息界面佈局