Java 在创建之前,查找适合屏幕的RecyclerView项目数
基本上,我试图通过编程找出一个RecyclerView中要容纳多少项(当然,用户也可以看到),以便确定要从缓存中提取多少项 我用的是LinearLayoutManager 另外,我知道LinearLayoutManager方法findLastVisibleItemPosition,但显然在这种情况下它是无用的,因为我们讨论的是初始化时间之前,而不是之后(因此返回-1) 我试着阅读文档或思考一个有创意但有效的想法,但我什么都没想到Java 在创建之前,查找适合屏幕的RecyclerView项目数,java,android,android-recyclerview,Java,Android,Android Recyclerview,基本上,我试图通过编程找出一个RecyclerView中要容纳多少项(当然,用户也可以看到),以便确定要从缓存中提取多少项 我用的是LinearLayoutManager 另外,我知道LinearLayoutManager方法findLastVisibleItemPosition,但显然在这种情况下它是无用的,因为我们讨论的是初始化时间之前,而不是之后(因此返回-1) 我试着阅读文档或思考一个有创意但有效的想法,但我什么都没想到 有什么想法吗?这听起来很有趣,但只有当你的高度(垂直滚动)或宽度(
有什么想法吗?这听起来很有趣,但只有当你的高度(垂直滚动)或宽度(水平滚动)是固定的,这意味着没有包装内容时,这才有效 这里没有示例代码,也没有测试:
getCount
创建一个带有setter的适配器,该setter在数据源为null/空时返回getCount
中,如果数据为空/空,则至少返回1onBindViewHolder()
可以处理空/不存在的数据onChildataTachStateChangeListener
添加到您的RecyclerView中,每次调用侦听器时,使用视图到视图.post(新建Runnable(){…增加适配器getCount…adapter.notifyItemInserted()}
(该Runnable是避免崩溃+烧毁所必需的)
OnChildataTachStateChangeListener
再次被调用>>比较getCount
和findLastVisibleItemPosition
。如果getCount>findLastVisibleItemPosition+1
删除该侦听器。适合ListView的固定大小视图数为findLastVisibleItemPosition+1
notifyDataSetChanged
getCount
从现在开始返回数据源长度onBindViewHolder
编辑:
onBindViewHolder
getItemCount()>getChildCount()
getChildCount()是RecyclerView中可见的视图数,则在超级调用后扩展LinearLayoutManager
并覆盖onLayoutChildren()
public class MainActivity extends AppCompatActivity {
private PreCountingAdapter mAdapter;
private RecyclerView mRecyclerView;
private PreCountLinearLayoutManager mPreCountLayoutManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mPreCountLayoutManager = new PreCountLinearLayoutManager(this,
LinearLayoutManager.VERTICAL, false);
mPreCountLayoutManager.setListener(new PreCountLinearLayoutManager.OnPreCountedListener() {
@Override
public void onPreCounted(int count) {
mPreCountLayoutManager.setListener(null);
loadData(count);
}
});
mRecyclerView.setLayoutManager(mPreCountLayoutManager);
mAdapter = new PreCountingAdapter();
mRecyclerView.setAdapter(mAdapter);
}
private void loadData(final int visibleItemCount) {
// load data here, probably asynchronously,
// for simplicity just an String Array with size visibleItemCount
final List<String> data = new ArrayList<>();
for (int i = 0; i < visibleItemCount; i++) {
data.add(String.format("child number #%d", i));
}
mRecyclerView.post(new Runnable() {
@Override
public void run() {
mAdapter.swapData(data);
}
});
}
@Override
protected void onDestroy() {
mPreCountLayoutManager.setListener(null);
super.onDestroy();
}
}
预计算适配器类
public class PreCountingAdapter extends RecyclerView.Adapter<PreCountingAdapter.ViewHolder> {
private List<String> mData;
public void swapData(List<String> data) {
mData = data;
notifyDataSetChanged();
}
public class ViewHolder extends RecyclerView.ViewHolder {
View mItemView;
TextView mTextView;
public ViewHolder(View itemView) {
super(itemView);
mTextView = (TextView) itemView.findViewById(R.id.text_view);
mItemView = itemView;
}
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
return new ViewHolder(inflater.inflate(R.layout.recycler_child, parent, false));
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
if (mData == null) {
// we are in precounting stage
holder.mItemView.setVisibility(View.INVISIBLE);
} else {
String item = mData.get(position);
holder.mItemView.setVisibility(View.VISIBLE);
holder.mTextView.setText(item);
}
}
@Override
public int getItemCount() {
return mData == null ? Integer.MAX_VALUE : mData.size();
}
}
公共类预计算适配器扩展了RecyclerView.Adapter{
私有列表数据;
公共无效交换数据(列表数据){
mData=数据;
notifyDataSetChanged();
}
公共类ViewHolder扩展了RecyclerView.ViewHolder{
视图;
文本视图mTextView;
公共视图持有者(视图项视图){
超级(项目视图);
mTextView=(TextView)itemView.findViewById(R.id.text\u视图);
mItemView=项目视图;
}
}
@凌驾
public ViewHolder onCreateViewHolder(视图组父级,int-viewType){
LayoutInflater充气器=LayoutInflater.from(parent.getContext());
返回新的视图保持架(充气器。充气(R.layout.recycler_child,parent,false));
}
@凌驾
公共无效onBindViewHolder(ViewHolder,int位置){
if(mData==null){
//我们正处于预计算阶段
holder.mItemView.setVisibility(视图不可见);
}否则{
字符串项=mData.get(位置);
holder.mItemView.setVisibility(View.VISIBLE);
holder.mTextView.setText(项目);
}
}
@凌驾
public int getItemCount(){
返回mData==null?Integer.MAX_值:mData.size();
}
}
我测试了它,因为最后一个视图从未连接,所以它无法工作。(Doh,在编写时我应该很清楚)添加了另一个解决方案,简单地测试了它,到目前为止它还可以工作。什么是修复?它从来没有修复过,它总是覆盖几乎所有可用空间(匹配父项),就像Android中的大多数视图一样。另外,你能更好地解释一下为什么你的解决方案会起作用吗?另外,我认为一个更简单的方法是实时计算recycler视图的高度,并根据每个项目的高度进行划分(然后需要通过编程或从维度xml进行设置,以便在创建项本身之前可以使用它…)对于Fixed,我的意思是每个子视图都必须有一个固定的高度,独立于要显示的数据。例如,textview总是有两行文本,RecyclerView本身可以是match_parent,这不是问题。虽然您可以计算每个项目的高度并简单地计算出数量,但当您开始计算marg时,它很快就会变得复杂另一方面,我的解决方案只是简单地欺骗LinearLayoutManager,让它完全完成它通常所做的工作:布局子视图,直到填充RecyclerView。此外,几乎没有开销,因为当真正的数据进入时,子视图会被回收和重用。您仍然可以更改字体大小,行数字等,它仍然会工作。
public class PreCountingAdapter extends RecyclerView.Adapter<PreCountingAdapter.ViewHolder> {
private List<String> mData;
public void swapData(List<String> data) {
mData = data;
notifyDataSetChanged();
}
public class ViewHolder extends RecyclerView.ViewHolder {
View mItemView;
TextView mTextView;
public ViewHolder(View itemView) {
super(itemView);
mTextView = (TextView) itemView.findViewById(R.id.text_view);
mItemView = itemView;
}
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
return new ViewHolder(inflater.inflate(R.layout.recycler_child, parent, false));
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
if (mData == null) {
// we are in precounting stage
holder.mItemView.setVisibility(View.INVISIBLE);
} else {
String item = mData.get(position);
holder.mItemView.setVisibility(View.VISIBLE);
holder.mTextView.setText(item);
}
}
@Override
public int getItemCount() {
return mData == null ? Integer.MAX_VALUE : mData.size();
}
}