冲刺三
今天完成的任务:实现笔记展示界面的上拉刷新和下拉加载
遇到的困难:
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(); } }); }
下拉提示信息界面布局