RecyclerView getChildAt(position)返回null

时间:2016-07-20 07:13:23

标签: android android-recyclerview

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

E / Item Pos:29

     

E / Item 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();
  }
}

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;
  }
}

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>

1 个答案:

答案 0 :(得分:6)

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

因此,在onClick事件的情况下,您无需查找视图并进行更改。您需要更改一些所谓的“设置”并撰写notifyDataSetChangednotifyItemChanged以进行更多优化。

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

@Override
public int getItemViewType(int position) {
    return position;
}

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

所以,根据你的问题,你会有某种:

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) {

    }
}));

在适配器中:

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)
}