以上就是给各位分享如何在较新版本的Android3.1和更高版本中实现FirebaseRecyclerAdapter?,其中也会对howtoupdateandroidversion进行解释,同时本文还
以上就是给各位分享如何在较新版本的Android 3.1和更高版本中实现Firebase Recycler Adapter?,其中也会对how to update android version进行解释,同时本文还将给你拓展Android RecyclerView 绘制流程及Recycler缓存,androidapp保活、Android RecyclerView(五)封装Holder与Adapter(Android 5.0 新特性)、android RecycleView Adapter 简单封装、android – FirebaseRecyclerAdapter – 如何在创建后更改数据库查询等相关知识,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!
本文目录一览:- 如何在较新版本的Android 3.1和更高版本中实现Firebase Recycler Adapter?(how to update android version)
- Android RecyclerView 绘制流程及Recycler缓存,androidapp保活
- Android RecyclerView(五)封装Holder与Adapter(Android 5.0 新特性)
- android RecycleView Adapter 简单封装
- android – FirebaseRecyclerAdapter – 如何在创建后更改数据库查询
如何在较新版本的Android 3.1和更高版本中实现Firebase Recycler Adapter?(how to update android version)
基本上,我想做的是使用,FirebaseRecyclerAdapter
并RecyclerView
使用我的自定义设计填充CardView
。较新版本的代码已更改,因此,我尝试实现它,但是没有用。这是我一年前编写的代码,可以很好地工作并填充我的代码RecyclerView
:
FirebaseRecyclerAdapter<DataClass,DataViewHolder> FBRA= new FirebaseRecyclerAdapter<DataClass, DataViewHolder>( DataClass, R.layout.myCardView, DataViewHolder.class, databaseReference ) { @Override protected void populateViewHolder(DataViewHolder viewHolder, DataClass model, int position) { viewHolder.setTitle(model.gettitle()); viewHolder.setDate(model.getDate()); } }; myRecyclerView.setAdapter(FBRA);
现在我们必须使用类似的东西,但是问题是此代码没有填充我的代码recyclerView
(我需要在此处进行哪些更改才能recyclerView
用cardView
填充我的代码?)
@Overrideprotected void onStart() { super.onStart(); Query query = FirebaseDatabase.getInstance() .getReference() .child("Official_Services"); FirebaseRecyclerOptions<ServiceClass> options = new FirebaseRecyclerOptions.Builder<ServiceClass>() .setQuery(query, ServiceClass.class) .build(); FirebaseRecyclerAdapter<ServiceClass, ServiceViewHolder> FBRA = new FirebaseRecyclerAdapter<ServiceClass, ServiceViewHolder>(options) { @NonNull @Override public ServiceViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int i) { View view = LayoutInflater.from(HomeActivity.this).inflate(R.layout.service_card, parent, false); return new ServiceViewHolder(view); } @Override protected void onBindViewHolder(@NonNull ServiceViewHolder holder, int position, @NonNull ServiceClass model) { holder.setServiceName(model.getServiceName()); holder.setServiceCaption(model.getServiceCaption()); } }; mServiceList.setAdapter(FBRA);}
这是我的ViewHolder
课:
public static class ServiceViewHolder extends RecyclerView.ViewHolder { public ServiceViewHolder(View itemView) { super(itemView); View mView = itemView; } public void setServiceName(String serviceName) { TextView sName = itemView.findViewById(R.id.serviceName); sName.setText(serviceName); } public void setServiceCaption(String serviceCaption) { TextView sCaption = itemView.findViewById(R.id.serviceCap); sCaption.setText(serviceCaption); }}
这是我的Getter和Setter的Model类:
public class ServiceClass {private String serviceName;private String serviceCode;private String serviceCaption;private String serviceIconUrl;public ServiceClass() {}public ServiceClass(String serviceName, String serviceCode, String serviceCaption, String serviceIconUrl) { this.serviceName = serviceName; this.serviceCode = serviceCode; this.serviceCaption = serviceCaption; this.serviceIconUrl = serviceIconUrl;}public String getServiceName() { return serviceName;}public String getServiceCode() { return serviceCode;}public String getServiceCaption() { return serviceCaption;}public String getServiceIconUrl() { return serviceIconUrl;}public void setServiceName(String serviceName) { this.serviceName = serviceName;}public void setServiceCode(String serviceCode) { this.serviceCode = serviceCode;}public void setServiceCaption(String serviceCaption) { this.serviceCaption = serviceCaption;}public void setServiceIconUrl(String serviceIconUrl) { this.serviceIconUrl = serviceIconUrl;}@Overridepublic String toString() { return "ServiceClass{" + "serviceName=''" + serviceName + ''\'''' + ", serviceCode=''" + serviceCode + ''\'''' + ", serviceCaption=''" + serviceCaption + ''\'''' + ", serviceIconUrl=''" + serviceIconUrl + ''\'''' + ''}'';}}
现在我需要做哪些更改?
这是我的整个Java文件:
public class HomeActivity extends AppCompatActivity { private RecyclerView mServiceList; private FirebaseDatabase mDatabase; private DatabaseReference myRef; FirebaseRecyclerAdapter<ServiceClass, ServiceViewHolder> FBRA; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_home); BottomNavigationViewEx bottomNavigationViewEx = findViewById(R.id.navViewBar); bottomNavigationViewEx.enableAnimation(false); bottomNavigationViewEx.enableShiftingMode(false); bottomNavigationViewEx.setTextVisibility(false); Calligrapher calligrapher = new Calligrapher(this); calligrapher.setFont(this, "Helvetica.ttf", true); mServiceList = findViewById(R.id.serviceRV); mServiceList.setHasFixedSize(true); mServiceList.setLayoutManager(new LinearLayoutManager(this)); mDatabase = FirebaseDatabase.getInstance(); myRef = mDatabase.getReference().child("Official_Services"); } @Override protected void onStart() { super.onStart(); FBRA.startListening(); Query query = myRef; FirebaseRecyclerOptions<ServiceClass> options = new FirebaseRecyclerOptions.Builder<ServiceClass>() .setQuery(query, ServiceClass.class) .build(); FBRA = new FirebaseRecyclerAdapter<ServiceClass, ServiceViewHolder>(options) { @NonNull @Override public ServiceViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int i) { View view = LayoutInflater.from(HomeActivity.this).inflate(R.layout.service_card, parent, false); return new ServiceViewHolder(view); } @Override protected void onBindViewHolder(@NonNull ServiceViewHolder holder, int position, @NonNull ServiceClass model) { holder.setServiceName(model.getServiceName()); holder.setServiceCaption(model.getServiceCaption()); } }; mServiceList.setAdapter(FBRA); } public static class ServiceViewHolder extends RecyclerView.ViewHolder { public ServiceViewHolder(View itemView) { super(itemView); View mView = itemView; } public void setServiceName(String serviceName) { TextView sName = itemView.findViewById(R.id.serviceName); sName.setText(serviceName); } public void setServiceCaption(String serviceCaption) { TextView sCaption = itemView.findViewById(R.id.serviceCap); sCaption.setText(serviceCaption); } }}
答案1
小编典典为了能够显示Firebase实时数据库中的数据,您需要开始侦听更改,为此您应该在onStart()
方法中添加以下代码行:
@Overrideprotected void onStart() { super.onStart(); FBRA.startListening();}
要停止监听foir更改,您需要在这样的onStop()
方法中添加以下代码行:
@Overrideprotected void onStop() { super.onStop(); if(FBRA != null) { FBRA.stopListening(); }}
PS也请不要忘记使FBRA
全局变量和FirebaseRecyclerAdapter<ServiceClass,ServiceViewHolder>
从对象的声明中删除。
Android RecyclerView 绘制流程及Recycler缓存,androidapp保活
addView(view, 0);
}
} else {
if (mShouldReverseLayout == (layoutState.mLayoutDirection
== LayoutState.LAYOUT_START)) {
adddisappearingView(view);
} else {
adddisappearingView(view, 0);
}
}
//测量被添加的 RecyclerView 中的子 ItemView 的宽高。
measureChildWithMargins(view, 0, 0);
…
//根据所设置的 decoration、Margins 等所有选项确定子 ItemView 的显示位置。
layoutDecoratedWithMargins(view, left, top, right, bottom);
…
}
onDraw
测量和布局都完成之后,就剩下最后的绘制操作了。
@Override
public void onDraw(Canvas c) {
super.onDraw©;
final int count = mItemdecorations.size();
for (int i = 0; i < count; i++) {
mItemdecorations.get(i).onDraw(c, this, mState);
}
}
如果有添加 Itemdecoration,则循环调用所有的 decoration 的 onDraw 方法,将其显示。至于所有的子 ItemView 则是通过 Android 渲染机制递归的调用子 ItemView 的 draw 方法显示到屏幕上。
绘制流程小结
RecyclerView 会将测量 onMeasure 和布局 onLayout 的工作委托给 LayoutManager 来执行,不同的 LayoutManager 会有不同风格的布局显示,这是一种策略模式。如下图:
缓存复用原理 Recycler
===============
缓存复用是 RecyclerView 中另一个非常重要的机制,这套机制主要实现了 ViewHolder 的缓存以及复用。
核心代码是在 Recycler 中完成的,它是 RecyclerView 中的一个内部类,主要用来缓存屏幕内 ViewHolder 以及部分屏幕外 ViewHolder,部分代码如下:
public final class Recycler {
//未与RecyclerView分离的ViewHolder列表
final ArrayList mAttachedScrap = new ArrayList<>();
//与RecyclerView分离的ViewHolder列表
ArrayList mChangedScrap = null;
//ViewHolder缓存列表
final ArrayList mCachedViews = new ArrayList();
//ViewHolder缓存池
RecycledViewPool mRecyclerPool;
//开发者可以控制的ViewHolder缓存的帮助类
private ViewCacheExtension mViewCacheExtension;
//默认情况下缓存个数是 2
static final int DEFAULT_CACHE_SIZE = 2;
}
Recycler 的缓存机制就是通过上图中的这些数据容器来实现的,实际上 Recycler 的缓存也是分级处理的,根据访问优先级从上到下可以分为 4 级,如下:
-
第一级缓存 mAttachedScrap&mChangedScrap
-
第二级缓存 mCachedViews
-
第三级缓存 ViewCacheExtension
-
第四级缓存 RecycledViewPool
各级缓存功能
RecyclerView 之所以要将缓存分成这么多块,是为了在功能上进行一些区分,并分别对应不同的使用场景。
第一级缓存 mAttachedScrap&mChangedScrap
是两个名为 Scrap 的 ArrayList,这两者主要用来缓存屏幕内的 ViewHolder。为什么屏幕内的 ViewHolder 需要缓存呢?
做过 App 开发的应该都熟悉通过下拉刷新列表中的内容,当刷新被触发时,只需要在原有的 ViewHolder 基础上进行重新绑定新的数据 data 即可,而这些旧的 ViewHolder 就是被保存在 mAttachedScrap 和 mChangedScrap 中。实际上当我们调用 RV 的 notifyXXX 方法时,就会向这两个列表进行填充,将旧 ViewHolder 缓存起来。
第二级缓存 mCachedViews
它用来缓存移除屏幕之外的 ViewHolder,默认情况下缓存个数是 2,不过可以通过 setViewCacheSize 方法来改变缓存的容量大小。如果 mCachedViews 的容量已满,则会根据 FIFO(先进先出) 的规则将旧 ViewHolder 抛弃,然后添加新的 ViewHolder。
通常情况下刚被移出屏幕的 ViewHolder 有可能接下来马上就会使用到,所以 RecyclerView 不会立即将其设置为无效 ViewHolder,而是会将它们保存到 cache 中,但又不能将所有移除屏幕的 ViewHolder 都视为有效 ViewHolder,所以它的默认容量只有 2 个。
第三级缓存 ViewCacheExtension
这是 RecyclerView 预留给开发人员的一个抽象类,在这个类中只有一个抽象方法。
public abstract static class ViewCacheExtension {
@Nullable
public abstract View getViewForPositionAndType(@NonNull Recycler recycler, int position,
int type);
}
开发人员可以通过继承 ViewCacheExtension,并复写抽象方法 getViewForPositionAndType 来实现自己的缓存机制。一般情况下我们不会自己实现也不建议自己去添加缓存逻辑,因为这个类的使用门槛较高(牛掰的人请忽略)。
第四级缓存 RecycledViewPool
RecycledViewPool 同样是用来缓存屏幕外的 ViewHolder,当 mCachedViews 中的个数已满(默认为 2),则从 mCachedViews 中淘汰出来的 ViewHolder 会先缓存到 RecycledViewPool 中。ViewHolder 在被缓存到 RecycledViewPool 时,会将内部的数据清理,因此从 RecycledViewPool 中取出来的 ViewHolder 需要重新调用 onBindViewHolder 绑定数据。这就同最早的 ListView 中的使用 ViewHolder 复用 convertView 的道理是一致的,因此 RV 也算是将 ListView 的优点完美的继承过来。
RecycledViewPool 还有一个重要功能,官方对其有如下解释:
RecycledViewPool 允许您在多个 RecyclerView 之间共享视图。
如果要跨 RecyclerViews 回收视图,请创建 RecycledViewPool 的实例并使用RecyclerView.setRecycledViewPool(RecycledViewPool)。
如果您不提供,RecyclerView 会自动为自己创建一个池。
可以看出,多个 RecycledView之间可以共享一个 RecycledViewPool,这对于多 tab 界面的优化效果会很显著。需要注意的是,RecycledViewPool 是根据 type 来获取 ViewHolder,每个 type 默认最大缓存 5 个。因此多个 RecyclerView 共享 RecycledViewPool 时,必须确保共享的 RecyclerView 使用的 Adapter 是同一个,或 view type 是不会冲突的。
RecyclerView 是如何从缓存中获取 ViewHolder 的
在上面介绍 onLayout 阶段时,有介绍在 layoutChunk 方法中通过调用 layoutState.next 方法拿到某个子 ItemView,然后添加到 RecyclerView 中。
linearlayoutmanager.LayoutState.next
View next(RecyclerView.Recycler recycler) {
if (mScrapList != null) {
return nextViewFromScrapList();
}
final View view = recycler.getViewForPosition(mCurrentPosition);
mCurrentPosition += mItemDirection;
return view;
}
//继续跟getViewForPosition(mCurrentPosition);
@NonNull
public View getViewForPosition(int position) {
return getViewForPosition(position, false);
}
//继续跟getViewForPosition
View getViewForPosition(int position, boolean dryRun) {
return tryGetViewHolderForPositionByDeadline(position, dryRun, FOREVER_NS).itemView;
}
可以看出最终调用 tryGetViewHolderForPositionByDeadline 方法来查找相应位置上的ViewHolder。
tryGetViewHolderForPositionByDeadline
在这个方法中会从上面介绍的 4 级缓存中依次查找:
@Nullable
ViewHolder tryGetViewHolderForPositionByDeadline(int position,
boolean dryRun, long deadlineNs) {
…
ViewHolder holder = null;
// 1)根据位置从scrap和mCachedViews返回位置的视图。
if (holder == null) {
//根据位置从scrap和mCachedViews返回位置的视图。
holder = getScrapOrHiddenorCachedHolderForPosition(position, dryRun);
}
if (holder == null) {
//获取这个位置的数据的类型(子View复写的方法)
final int type = mAdapter.getItemViewType(offsetPosition);
// 2)根据ID在scrap和cache 中查找
if (mAdapter.hasstableIds()) {
holder = getScrapOrCachedViewForId(mAdapter.getItemId(offsetPosition),type, dryRun);
}
//从ViewCacheExtension获取ViewHolder
if (holder == null && mViewCacheExtension != null) {
//返回 绑定到给定位置的视图,如果没有可重用的视图,则为NULL
final View view = mViewCacheExtension.getViewForPositionAndType(this, position, type);
}
//3)从RecycledViewPool获取ViewHolder
if (holder == null) {
//4)从RecycledViewPool获取ViewHolder
holder = getRecycledViewPool().getRecycledView(type);
}
if (holder == null) {
//5)如果在各级缓存中都没有找到相应的 ViewHolder,则会使用 Adapter 中的 createViewHolder 方法创建一个新的 ViewHolder。
holder = mAdapter.createViewHolder(RecyclerView.this, type);
}
}
…
最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上我搜集整理的2019-2021BATJ 面试真题解析,我把大厂面试中常被问到的技术点整理成了PDF,包知识脉络 + 诸多细节。
节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。
一键领取:【Android超硬核面试资料】
《960全网最全Android开发笔记》
《379页Android开发面试宝典》
历时半年,我们整理了这份市面上最全面的安卓面试题解析大全
包含了腾讯、百度、小米、阿里、乐视、美团、58、猎豹、360、新浪、搜狐等一线互联网公司面试被问到的题目。熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率。
如何使用它?
1.可以通过目录索引直接翻看需要的知识点,查漏补缺。
2.五角星数表示面试问到的频率,代表重要推荐指数
《507页Android开发相关源码解析》
只要是程序员,不管是Java还是Android,如果不去阅读源码,只看api文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。
真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。
腾讯、字节跳动、阿里、百度等BAT大厂 2019-2021面试真题解析
列出的知识点会大大增加通过前两轮技术面试的几率。
如何使用它?
1.可以通过目录索引直接翻看需要的知识点,查漏补缺。
2.五角星数表示面试问到的频率,代表重要推荐指数
[外链图片转存中…(img-jhdbnqYP-1643775391899)]
《507页Android开发相关源码解析》
只要是程序员,不管是Java还是Android,如果不去阅读源码,只看api文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。
真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。
[外链图片转存中…(img-fR26hYNt-1643775391900)]
腾讯、字节跳动、阿里、百度等BAT大厂 2019-2021面试真题解析
[外链图片转存中…(img-COB2ausY-1643775391900)]
资料太多,全部展示会影响篇幅,暂时就先列举这些部分截图,大家可以点击这里自行获取。
Android RecyclerView(五)封装Holder与Adapter(Android 5.0 新特性)
Android RecyclerView(五)封装Holder与Adapter(Android 5.0 新特性)
1 效果
2 BaseHolder的封装
public class BaseViewHolder extends RecyclerView.ViewHolder {
private SparseArray<View> views;
public BaseViewHolder(View view) {
super(view);
this.views = new SparseArray<>();
}
public <T extends View> T getView(int viewId) {
View view = views.get(viewId);
if (view == null) {
view = itemView.findViewById(viewId);
views.put(viewId, view);
}
return (T) view;
}
public View getRootView() {
return itemView;
}
}
3 BaseRecyclerViewAdapter 的封装
public abstract class BaseRecyclerViewAdapter<T> extends RecyclerView.Adapter<BaseViewHolder> {
private Context context;
private LayoutInflater inflater;
private List<T> datas;
private int layoutId;
protected OnItemClickListner onItemClickListner;//单击事件
protected OnItemLongClickListner onItemLongClickListner;//长按单击事件
private boolean clickFlag = true;//单击事件和长单击事件的屏蔽标识
/**
* @param context 上下文对象
* @param datas 数据
* @param layoutId 布局ID
*/
public BaseRecyclerViewAdapter(Context context, List<T> datas, int layoutId) {
this.context = context;
this.datas = datas;
this.layoutId = layoutId;
this.inflater = LayoutInflater.from(context);
}
@Override
public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//创建ViewHolder
return new BaseViewHolder(inflater.inflate(layoutId, parent, false));
}
@Override
public void onBindViewHolder(BaseViewHolder holder, int position) {
//数据绑定
bindData(holder, datas.get(position), position);
}
@Override
public int getItemCount() {
return datas == null ? 0 : datas.size();
}
protected abstract void bindData(BaseViewHolder holder, T data, int position);
//设置Item点击事件
public void setOnItemClickListner(OnItemClickListner onItemClickListner) {
this.onItemClickListner = onItemClickListner;
}
//设置Item长按点击事件
public void setOnItemLongClickListner(OnItemLongClickListner onItemLongClickListner) {
this.onItemLongClickListner = onItemLongClickListner;
}
public interface OnItemClickListner {
void onItemClickListner(View v, int position);
}
public interface OnItemLongClickListner {
void onItemLongClickListner(View v, int position);
}
}
4 使用
4.1 创建 CustomViewHolder
private class CustomViewHolder extends BaseRecyclerViewAdapter<String>{
/**
* @param context 上下文对象
* @param datas 数据
* @param layoutId 布局ID
*/
public CustomViewHolder(Context context, List<String> datas, int layoutId) {
super(context, datas, layoutId);
}
@Override
protected void bindData(BaseViewHolder holder, String data, int position) {
TextView textView = holder.getRootView().findViewById(R.id.tv_item_text);
textView.setText("测试数据 "+position);
}
}
4.2 对RecyclerView 设置 CustomViewHolder
RecyclerView contentRecyclerView = (RecyclerView) findViewById(R.id.rv_main_content);
//初始化数据
List<String> list = new ArrayList<>();
for (int i = 0; i < 20; i++) {
list.add("智慧安卓 -- "+i);
}
//初始化Adapter
ListRecyclerAdapter recyclerAdapter = new ListRecyclerAdapter(this.getApplication(),list);
//初始化排列布局
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this.getApplicationContext());
//设置
contentRecyclerView.setLayoutManager(linearLayoutManager);
//设置水平排列
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
//设置adapter
CustomViewHolder customViewHolder = new CustomViewHolder(this.getApplicationContext(), list, R.layout.item);
contentRecyclerView.setAdapter(customViewHolder);
本文同步分享在 博客“早起的年轻人”(CSDN)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。
android RecycleView Adapter 简单封装
早些时候我们使用系统提供个的 BaseAdapter 的时候为了满足大家的需要,我们总会对 BaseAdapter 做一层上层的封装,然后对于实际业务我们只需要关心 getView 里面的 View 即可,是代码可读性和可维护性更高,特别是在多 View 的界面,这个优势就体现出来了,自从 Android 5.0 后系统提供的,先不说效率如何,这个既然是 Google 为我们提供的,我们姑且用之,不过说实话,对于它的写法不习惯他的人看着很是麻烦,其实这个类无外乎继承自 RecyclerView.Adapter 然后提供一个 HolderView。
如下:
public class DetailParamAdapter extends RecyclerView.Adapter<ParamHolderView> {
private List<ProductParamEntity> list;
private LayoutInflater mInflater;
private Context mContext = null;
public DetailParamAdapter(Context context) {
this.mContext = context;
mInflater = LayoutInflater.from(context);
}
public void setList(List<ProductParamEntity> list) {
this.list = list;
notifyDataSetChanged();
}
public OnItemClickListener mOnItemClickListener;
public interface OnItemClickListener {
void onItemClick(View view, int position);
}
public void setOnItemClickListener(OnItemClickListener mOnItemClickLitener) {
this.mOnItemClickListener = mOnItemClickLitener;
}
@Override
public ParamHolderView onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R.layout.item_product_param, parent, false);
ParamHolderView holder = new ParamHolderView(view);
return holder;
}
@Override
public void onBindViewHolder(final ParamHolderView holder, final int position) {
ProductParamEntity bean = list.get(position);
if (bean != null) {
holder.itemTitle.setText(bean.title);
holder.itemContent.setText(bean.content);
}
}
@Override
public int getItemCount() {
return list.size();
}
}
class ParamHolderView extends RecyclerView.ViewHolder {
@BindView(R.id.item_title)
TextView itemTitle;
@BindView(R.id.item_content)
TextView itemContent;
public ParamHolderView(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
itemView.setTag(this);
}
}
不过我们可不可以对上面的写法来一个精简呢?
其实分析下,adapter 对我们有用的就两个方法,一个是获取 adapter 的 View,然后是绑定数据 OnBindData,至于数据的来源,我们可以借鉴 RecyclerView.Adapter 做一个泛型。
有了上面的思路,首先我们要获取 adapter 的 View,然后将它赋给 onCreateViewHolder 返回的 view 对象。所以我们的构造可以这么写,
public BaseRecycleAdapter(Context context, List<T> list, int... layoutIds) {
this.mContext = context;
this.mList = list;
this.layoutIds = layoutIds;
this.mLInflater = LayoutInflater.from(mContext);
}
public BaseRecycleHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType < 0 || viewType > layoutIds.length) {
throw new ArrayIndexOutOfBoundsException("layoutIndex");
}
if (layoutIds.length == 0) {
throw new IllegalArgumentException("not layoutId");
}
int layoutId = layoutIds[viewType];
View view = mConvertViews.get(layoutId);
if (view == null) {
view = mLInflater.inflate(layoutId, parent, false);
}
BaseRecycleHolder viewHolder = (BaseRecycleHolder) view.getTag();
if (viewHolder == null || viewHolder.getLayoutId() != layoutId) {
viewHolder = new BaseRecycleHolder(mContext, layoutId, view);
return viewHolder;
}
return viewHolder;
}
然后我们需要绑定界面了,由于各个页面的对于的元素不一样,所以这个方法我们需要根据实际情况去动态绑定数据,所以我们需要写一个抽象方法去让用户实现,这个抽象方法主要包含 ViewHolder 界面,位置,还有 Item 的元素(其实这个大可以不要)
protected abstract void onBindData(BaseRecycleHolder viewHolder, int position, T item);
@Override
public void onBindViewHolder(BaseRecycleHolder holder, int position) {
final T item = mList.get(position);
onBindData(holder, position, item);
}
当然我们这个 Adapter 基础的类可能还需要一些常用入 add,clear,del 等操作方法。其完整的代码如下:
public abstract class BaseRecycleAdapter<T> extends RecyclerView.Adapter<BaseRecycleHolder> implements RecyclerViewHelper<T> {
protected Context mContext;
protected List<T> mList;
protected int[] layoutIds;
protected LayoutInflater mLInflater;
private SparseArray<View> mConvertViews = new SparseArray<>();
public BaseRecycleAdapter(Context context, List<T> list, int... layoutIds) {
this.mContext = context;
this.mList = list;
this.layoutIds = layoutIds;
this.mLInflater = LayoutInflater.from(mContext);
}
@Override
public BaseRecycleHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType < 0 || viewType > layoutIds.length) {
throw new ArrayIndexOutOfBoundsException("layoutIndex");
}
if (layoutIds.length == 0) {
throw new IllegalArgumentException("not layoutId");
}
int layoutId = layoutIds[viewType];
View view = mConvertViews.get(layoutId);
if (view == null) {
view = mLInflater.inflate(layoutId, parent, false);
}
BaseRecycleHolder viewHolder = (BaseRecycleHolder) view.getTag();
if (viewHolder == null || viewHolder.getLayoutId() != layoutId) {
viewHolder = new BaseRecycleHolder(mContext, layoutId, view);
return viewHolder;
}
return viewHolder;
}
@Override
public void onBindViewHolder(BaseRecycleHolder holder, int position) {
final T item = mList.get(position);
onBindData(holder, position, item);
}
@Override
public int getItemCount() {
return mList == null ? 0 : mList.size();
}
@Override
public int getItemViewType(int position) {
return getLayoutIndex(position, mList.get(position));
}
/**
* 指定item布局样式在layoutIds的索引。默认为第一个
*/
public int getLayoutIndex(int position, T item) {
return 0;
}
protected abstract void onBindData(BaseRecycleHolder viewHolder, int position, T item);
@Override
public boolean addAll(List<T> list) {
boolean result = mList.addAll(list);
notifyDataSetChanged();
return result;
}
@Override
public boolean addAll(int position, List list) {
boolean result = mList.addAll(position, list);
notifyDataSetChanged();
return result;
}
@Override
public void add(T data) {
mList.add(data);
notifyDataSetChanged();
}
@Override
public void add(int position, T data) {
mList.add(position, data);
notifyDataSetChanged();
}
@Override
public void clear() {
mList.clear();
notifyDataSetChanged();
}
@Override
public boolean contains(T data) {
return mList.contains(data);
}
@Override
public T getData(int index) {
return mList.get(index);
}
@Override
public void modify(T oldData, T newData) {
modify(mList.indexOf(oldData), newData);
}
@Override
public void modify(int index, T newData) {
mList.set(index, newData);
notifyDataSetChanged();
}
@Override
public boolean remove(T data) {
boolean result = mList.remove(data);
notifyDataSetChanged();
return result;
}
@Override
public void remove(int index) {
mList.remove(index);
notifyDataSetChanged();
}
}
当然这里还有好多的辅助类,这里就不在详解解释了,那最好我们怎么用呢?很简单,来一个之前的例子:
public class ParamRecycleAdapter extends BaseRecycleAdapter<ProductParamEntity> {
public ParamRecycleAdapter(Context context, List<ProductParamEntity> list) {
super(context, list, R.layout.item_product_param);
}
@Override
protected void onBindData(BaseRecycleHolder viewHolder, int position, ProductParamEntity item) {
viewHolder.setText(R.id.item_title, item.title)
.setText(R.id.item_content, item.content);
}
}
我们只要注意上面标颜色的部分即可。我已经将这个封装为一个库文件,如果有需要的可以自己打包 aar 或者 jar,相关资料请参照: 打包 aar,代码已经上传(文章最后)。
对于之前的 Baseadapter 这里也贴给大家:
public abstract class BasicAdapter<T> extends BaseAdapter {
public Context mContext = null;
protected LayoutInflater inflaterFactory = null;
protected List<T> mList = new ArrayList<T>();
public BasicAdapter() {
super();
}
public BasicAdapter(Context context) {
this.mContext = context;
inflaterFactory = LayoutInflater.from(mContext);
}
public BasicAdapter(List<T> list) {
if (list != null) {
mList = list;
}
}
public BasicAdapter(Context context, List<T> list) {
this(context);
this.mList = list;
}
public void setList(List<T> list) {
if (list != null) {
mList = list;
notifyDataSetChanged();
}
}
public boolean addList(List<T> list) {
if (list != null && list.size() > 0) {
mList.addAll(list);
notifyDataSetChanged();
return true;
}
return false;
}
public boolean add(T t) {
if (t != null) {
mList.add(t);
notifyDataSetChanged();
return true;
}
return false;
}
public boolean add(int position, T t) {
if (t != null && getCount() >= position) {
mList.add(position, t);
notifyDataSetChanged();
return true;
}
return false;
}
public void remove(T t) {
if (mList.remove(t)) {
notifyDataSetChanged();
}
}
public void remove(List<T> list) {
if (mList.remove(list)) {
notifyDataSetChanged();
}
}
public void remove(int index) {
if (index >= 0 && index < mList.size()) {
mList.remove(index);
notifyDataSetChanged();
}
}
public void clear() {
if (mList != null) {
mList.clear();
notifyDataSetChanged();
}
}
public List<T> getList() {
return mList;
}
@Override
public int getCount() {
if (mList != null && mList.size() > 0) {
return mList.size();
} else
return 0;
}
@Override
public T getItem(int position) {
if (mList!=null){
return mList.get(position);
}else
return null;
}
public T getLastItem() {
if (mList.size() > 0) {
return mList.get(mList.size() - 1);
}
return null;
}
@Override
public long getItemId(int position) {
return position;
}
public <V extends View> V inflate(int resource, ViewGroup root, boolean attachToRoot) {
if (inflaterFactory == null) {
inflaterFactory = LayoutInflater.from(mContext);
}
return (V) inflaterFactory.inflate(resource, root, attachToRoot);
}
public <V extends View> V inflate(int resource, ViewGroup root) {
return inflate(resource, root, root != null);
}
public <V extends View> V inflate(int resource) {
return inflate(resource, null, false);
}
}
最后贴上 RecycleView.Adapter 的封装库地址: 点击打开链接
本文同步分享在 博客 “xiangzhihong8”(CSDN)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与 “OSC 源创计划”,欢迎正在阅读的你也加入,一起分享。
android – FirebaseRecyclerAdapter – 如何在创建后更改数据库查询
问题
我有一个通过FirebaseRecyclerAdapter在android中显示的项目列表.我创建了这个适配器,在所有项目列表上都有一个数据库引用(让我们说“帖子”).帖子还显示类别,如果用户点击类别,我想更新列表以仅显示该类别的项目.
我试过的解决方案不起作用
我在“类别”textview上放置了一个单击侦听器,当用户单击它时,我尝试使用新的数据库查询实例化一个新的适配器,但它不起作用.
其他想法:
在adpater之外做:
创建一个新的Intent以重新启动片段并使用新查询创建一个新的适配器
题
有人处理相同的情况,在用户点击您要过滤由adpater检索的原始项目列表?
什么是最好的解决方案?
细节
protected void populateViewHolder(final PostViewHolder viewHolder, final Post post, final int position) {
/* Set the post text, author and category */
viewHolder.postText.setText(post.getText());
viewHolder.postAuthor.setText(post.getAuthor());
viewHolder.postCategory.setText(post.getCategory());
/* Set a listener on category so that
I refresh data with only that category */
viewHolder.quoteCategory.setonClickListener(new View.OnClickListener() {
Post selectedPost = getItem(position);
@Override
public void onClick(View v) {
String category = selectedPost.getCategory();
// !!!! Now I HAVE TO CHANGE DATA SET !!! ///
我想现在我可以创建一个带有正确Db引用的新适配器的新片段……但这是最好的方法吗?
有没有办法在填充视图中使用相同的Adapater传递另一个查询?
解决方法:
单击发生时,尝试在适配器上调用.notifyDatasetChanged().使用新的firebase数据更改数据集后.
今天关于如何在较新版本的Android 3.1和更高版本中实现Firebase Recycler Adapter?和how to update android version的分享就到这里,希望大家有所收获,若想了解更多关于Android RecyclerView 绘制流程及Recycler缓存,androidapp保活、Android RecyclerView(五)封装Holder与Adapter(Android 5.0 新特性)、android RecycleView Adapter 简单封装、android – FirebaseRecyclerAdapter – 如何在创建后更改数据库查询等相关知识,可以在本站进行查询。
本文标签: