Implementation Idea
- Distinguish different items you can define base Item class like this
public abstract class ListItem { public final Type mType; protected ListItem(Type type){ mType = type; } public int typeToInteger(){ return mType.toInteger(); } enum Type{ NORMAL(0), PROGRESS(1); private int mOrder; Type(int type){ mOrder = type; } public int toInteger(){ return mOrder; } } }
- Write RecyclerView Adapter
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder>{ private final List<ListItem> mDataSet; private final RecyclerView mRecyclerView; public MyAdapter(List<ListItem> dataSet, RecyclerView recyclerView){ mDataSet = dataSet; mRecyclerView = recyclerView; } @Override public int getItemViewType(int position) { ListItem item = mDataSet.get(position); return item.mType.toInteger(); } @Override public int getItemCount() { return mDataSet.size(); } public static class MyViewHolder extends RecyclerView.ViewHolder{ public final ListItem.Type mType; public MyViewHolder(View v, ListItem.Type type){ super(v); mType = type; } } }
the
ListItem.Type
will be used useful to distinguish between them. -
Now Inheritance
class MyViewHolder
andclass ListItem
- Items
public class ProgressItem extends ListItem{ public ProgressItem(){ super(Type.PROGRESS); } }
public class NormalItem extends ListItem{ private String text; public NormalItem(String data){ super(Type.NORMAL); text = data; } public String getText(){ return text; } }
- ViewHolders
TheMyAdapter
can use theseViewHolder
for theonCreateViewHolder
.public class ProgressViewHolder extends MyAdapter.MyViewHolder{ public ProgressViewHolder(View v){ super(v, ListItem.Type.PROGRESS); } }
public class NormalViewHolder extends MyAdapter.MyViewHolder{ public final TextView mTextView; public NormalViewHolder(View v) { super(v, ListItem.Type.NORMAL); mTextView = (TextView) v.findViewById(R.id.txt_field); } }
- Items
- Override RecyclerView.Adapter’s methods (
class MyAdapter
)@NonNull @Override public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View v; if(viewType == ListItem.Type.NORMAL.toInteger()){ v = LayoutInflater.from(parent.getContext()) .inflate(R.layout.recycler_item, parent, false); return new NormalViewHolder(v); } else{//progress v = LayoutInflater.from(parent.getContext()) .inflate(R.layout.progress, parent, false); return new ProgressViewHolder(v); } } @Override public void onBindViewHolder(@NonNull MyViewHolder holder, int position) { if(holder.mType == ListItem.Type.NORMAL){ NormalItem tmp = (NormalItem) mDataSet.get(position); ((NormalViewHolder) holder).mTextView.setText(tmp.getText()); } } @Override public int getItemViewType(int position) { ListItem item = mDataSet.get(position); return item.mType.toInteger(); } @Override public int getItemCount() { return mDataSet.size(); }
Now, you can understand why the
ListItem.Type
is needed.recyclerView.Adapter
provides thegetItemViewType
so that we can distinguish between the ListItems. When RecyclerView creates a new View for ListItem, the Adapter can load different layouts depends onListItem.type
In this example, I used if-else cause there are only two different kinds of ListItem. - Finally, you can use it!
for display progress barprivate void setProgress(){ mAdapter.addItem(new ProgressItem()); mAdapter.notifyDataSetChanged(); }
you can add
RecyclerView.OnScrollListener
reference_stack_over_flowrecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); if(!recyclerView.canScrollVertically(1) && newState == RecyclerView.SCROLL_STATE_IDLE){ doTask(); } } });
the
doTask()
isAsyncTask
for load more data from the source.