RecyclerView getChildAt(position)返回null

Tec*_*oid 3 android android-recyclerview

  • 我在我的应用程序中实现Recyclerview,我需要在其项目上单击更新另一个列表视图,这就是为什么我在活动中实现了onClick事件.它工作正常.
  • 但我还需要High Light RecyclerView选择的视图和其他都保持正常.
  • 为此,我使用RecyclerView getChild方法使所有视图正常,然后选择视图突出显示.
  • 我意识到它仅适用于RecyclerView的Visible视图.但是我需要对Recyclerview进行正常的所有视图,如果我使用更大位置的getChildAt,那么总可见计数会返回空指针异常.
    • 记录我得到的

E /项目位置:29

E /项目Rv:15

E/Child适配器:30

MainActivity.java

public class MainActivity extends Activity {
RecyclerView reView;
ArrayList<RvModel> rvModels;
revAdapter adapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    reView = (RecyclerView) findViewById(R.id.reView);
    reView.setLayoutManager(new GridLayoutManager(MainActivity.this, 3));

    rvModels = new ArrayList<>();
    adapter = new revAdapter(MainActivity.this, rvModels);
    reView.setAdapter(adapter);
    prepareData();
    reView.addOnItemTouchListener(new RecyclerItemClickListener(MainActivity.this, reView, new RecyclerItemClickListener.OnItemClickListener() {
        @Override
        public void onItemClick(View view, int position) {
            Log.e("Item Pos", "" + position);
            Log.e("Item Rv", "" + reView.getChildCount());
            Log.e("Child Adapter", "" + reView.getAdapter().getItemCount());

            for (int i = 0; i < reView.getChildCount(); i++) {
                View v = reView.getChildAt(i);
                TextView txtText = (TextView) v.findViewById(R.id.txtText);

                txtText.setBackgroundColor(Color.WHITE);
                txtText.setTextColor(Color.BLUE);
            }
            TextView txtText = (TextView) view.findViewById(R.id.txtText);
            txtText.setBackgroundColor(Color.BLUE);
            txtText.setTextColor(Color.WHITE);
        }

        @Override
        public void onLongItemClick(View view, int position) {

        }
    }));
}

private void prepareData() {
    rvModels.clear();
    for (int i = 0; i < 30; i++) {
        RvModel rvModel = new RvModel();
        rvModel.setTitle("Item : " + i);
        rvModels.add(rvModel);
    }
    adapter.notifyDataSetChanged();
  }
}
Run Code Online (Sandbox Code Playgroud)

revAdapter.java

public class revAdapter extends RecyclerView.Adapter<revAdapter.ViewHolder> {
Context context;
ArrayList<RvModel> rvModels;
LayoutInflater inflater;

public revAdapter(Context context, ArrayList<RvModel> rvModels) {
    this.context = context;
    this.rvModels = rvModels;
    inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}

public class ViewHolder extends RecyclerView.ViewHolder {
    ImageView ivIcon;
    TextView txtText;

    public ViewHolder(View itemView) {
        super(itemView);
        ivIcon = (ImageView) itemView.findViewById(R.id.ivIcon);
        txtText = (TextView) itemView.findViewById(R.id.txtText);
    }
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View itemView = inflater.inflate(R.layout.rv_raw, parent, false);
    return new ViewHolder(itemView);
}

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    RvModel rvModel = rvModels.get(position);
    holder.txtText.setText(rvModel.getTitle());
}

@Override
public int getItemCount() {
    return rvModels.size();
}

@Override
public int getItemViewType(int position) {
    return position;
  }
}
Run Code Online (Sandbox Code Playgroud)

rv_raw.xml

<?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="match_parent"
android:gravity="center"
android:orientation="vertical">

<LinearLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="10dp">

    <ImageView
        android:id="@+id/ivIcon"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:src="@mipmap/ic_launcher" />

    <TextView
        android:id="@+id/txtText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Medium Text"
        android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>
Run Code Online (Sandbox Code Playgroud)

Mic*_*sin 7

问题是像列表视图一样的recyclelerView有多少子视图(项目)取决于你的屏幕大小,而不是你有多少项目.它会阻止应用程序出现OOM异常.例如,如果您有1M项,那么,从您的逻辑来看,Recycler视图必须创建1M子视图,这很糟糕.您可以在此处阅读有关列表视图的更多信息(回收站视图以相同方式工作)

因此,在您的情况下,onClick您不需要查找视图并进行更改.您需要更改一些所谓的"设置"并写入notifyDataSetChangednotifyItemChanged更多优化.

我也检查了你的代码,我求你了.请,请删除此覆盖功能:

@Override
public int getItemViewType(int position) {
    return position;
}
Run Code Online (Sandbox Code Playgroud)

您对所有项目使用相同的持有者,因此您的回收站视图中只有一种类型的视图.以您告知回收站视图的方式覆盖此方法,每个项目使用不同的布局,这会降低性能.

所以,根据你的问题,你将有某种形式:

reView.addOnItemTouchListener(new RecyclerItemClickListener(MainActivity.this, reView, new RecyclerItemClickListener.OnItemClickListener() {
    @Override
    public void onItemClick(View view, int position) {
        Log.e("Item Pos", "" + position);
        Log.e("Item Rv", "" + reView.getChildCount());
        Log.e("Child Adapter", "" + reView.getAdapter().getItemCount());

        if (!adapter.isChecked(position)) {
            adapter.setChecked(position);
        }
    }

    @Override
    public void onLongItemClick(View view, int position) {

    }
}));
Run Code Online (Sandbox Code Playgroud)

在适配器中:

private int checkedPosition = -1;

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    RvModel rvModel = rvModels.get(position);
    holder.txtText.setText(rvModel.getTitle());

    if (position == checkedPosition) {
        txtText.setBackgroundColor(Color.BLUE);
        txtText.setTextColor(Color.WHITE);
    } else {
        txtText.setBackgroundColor(Color.WHITE);
        txtText.setTextColor(Color.BLUE);
    }
}

public boolean isChecked(int position) {
    return checkedPosition == position;
}

public void setChecked(int position) {
    int prevChecked = checkedPosition;
    checkedPosition = position;

    if (prevChecked != -1) {
        notifyItemChanged(prevChecked);
    }
    notifyItemChanged(checkedPosition)
}
Run Code Online (Sandbox Code Playgroud)