Android 如何强制RecyclerView.Adapter在所有元素上调用onBindViewHolder()
我有一个Android 如何强制RecyclerView.Adapter在所有元素上调用onBindViewHolder(),android,textview,android-recyclerview,Android,Textview,Android Recyclerview,我有一个VerticalGridView,它使用RecyclerView.Adapter来填充元素。我发现,如果潜在元素不在视口中,则不会调用onBindViewHolder()方法。不幸的是,这会导致来自不同方法的NullPointerException,因为我正在onBindViewHolder()方法中捕获TextView引用,并将其传递给外部变量以供以后操作 @Override public void onBindViewHolder(RecyclerView.ViewHolder ho
VerticalGridView
,它使用RecyclerView.Adapter
来填充元素。我发现,如果潜在元素不在视口中,则不会调用onBindViewHolder()
方法。不幸的是,这会导致来自不同方法的NullPointerException
,因为我正在onBindViewHolder()
方法中捕获TextView
引用,并将其传递给外部变量以供以后操作
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
final ViewHolder viewHolder = (ViewHolder) holder;
viewHolder.txtCategoryName.setText(categories.get(position).getStrCategory());
categories.get(position).setTxtViewReference(viewHolder.txtCategoryDefectTotal);
viewHolder.categoryBoxRoot.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
for(CategoryListItem catItem : categories){
if(catItem.getStrCategory().equals(viewHolder.txtCategoryName.getText())){
int index = Defects.getInstance().getCategories().indexOf(catItem) + 1;
MainInterface.grids.get(index).bringToFront();
MainInterface.grids.get(index).setVisibility(View.VISIBLE);
for(VerticalGridView grid : MainInterface.grids){
int gridIndex = MainInterface.grids.indexOf(grid);
if(gridIndex != index){
grid.setVisibility(View.INVISIBLE);
}
}
break;
}
}
}
});
据我所知,对TextView
的引用是在实例化Viewholder
对象时创建的
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView txtCategoryName;
public TextView txtCategoryDefectTotal;
public View categoryBoxRoot;
public ViewHolder(View itemView) {
super(itemView);
txtCategoryName = (TextView) itemView.findViewById(R.id.textViewCategoryName);
txtCategoryDefectTotal = (TextView) itemView.findViewById(R.id.textViewCategoryTotalDefects);
categoryBoxRoot = itemView.findViewById(R.id.root_category_box);
}
}
当适配器
实例化时,是否有方法强制对所有元素至少调用一次onBindViewHolder()
我试图提出这些建议,但没有成功
我理解在所有元素上强制执行onBindViewHolder()
,会违反规则。因此,我愿意接受关于如何捕捉TextView
参考的任何其他建议
作为这个问题的临时解决方案,我能够在生成NullPointerException
的方法周围使用try-catch块。然而,我担心缺乏参考意味着我将来可能会引入错误。了解流程
public class ThemeGridAdapter extends RecyclerView.Adapter<ThemeGridAdapter.ViewHolder> {
private OnItemClickedListener listener;
private List<Theme> mDataset;
public static class ViewHolder extends RecyclerView.ViewHolder {
public TextView title;
public TextView subtitle;
// public SimpleDraweeView image;
public ImageView img;
public ViewGroup container;
public ViewHolder(RelativeLayout v) {
super(v);
container = v;
title = (TextView) v.findViewById(R.id.theme_name_text);
subtitle = (TextView) v.findViewById(R.id.theme_name_type);
// image = (SimpleDraweeView) v.findViewById(R.id.cell_img);
img = (ImageView) v.findViewById(R.id.cell_img);
}
}
public ThemeGridAdapter(List<Theme> dataset) {
mDataset = dataset;
}
@Override
public ThemeGridAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
RelativeLayout v = (RelativeLayout) LayoutInflater.from(parent.getContext())
.inflate(R.layout.cell, parent, false);
return new ViewHolder(v);
}
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
holder.title.setText(mDataset.get(position).getTitle());
holder.subtitle.setText(mDataset.get(position).getAuthor());
// Uri uri = Uri.parse(mDataset.get(position).getUrl());
holder.img.setImageResource(mDataset.get(position).getImage());
// holder.image.setImageURI(uri);
holder.container.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (listener != null)
listener.onItemClicked(holder.getAdapterPosition());
}
});
}
@Override
public int getItemCount() {
return mDataset.size();
}
public void setListener(OnItemClickedListener listener) {
this.listener = listener;
}
}
public类ThemeGridAdapter扩展了RecyclerView.Adapter{
私人监听;
私有列表数据集;
公共静态类ViewHolder扩展了RecyclerView.ViewHolder{
公共文本视图标题;
公共文本视图字幕;
//公众形象;
公共图像视图img;
公共视图组容器;
公共视图持有者(相对视图v){
超级(五);
容器=v;
title=(TextView)v.findViewById(R.id.theme\u name\u text);
subtitle=(TextView)v.findViewById(R.id.theme\u name\u type);
//image=(simpledraweview)v.findViewById(R.id.cell\u img);
img=(ImageView)v.findViewById(R.id.cell\u img);
}
}
公共主题集成适配器(列表数据集){
mDataset=数据集;
}
@凌驾
public ThemeGridAdapter.ViewHolder onCreateViewHolder(视图组父级、,
int视图类型){
RelativeLayout v=(RelativeLayout)LayoutFlater.from(parent.getContext())
.充气(R.layout.cell,父级,假);
返回新的视图持有者(v);
}
@凌驾
公共无效onBindViewHolder(最终视图持有人,最终整型位置){
holder.title.setText(mDataset.get(position.getTitle());
holder.subtitle.setText(mDataset.get(position.getAuthor());
//Uri=Uri.parse(mDataset.get(position.getUrl());
holder.img.setImageResource(mDataset.get(position.getImage());
//holder.image.setImageURI(uri);
holder.container.setOnClickListener(新视图.OnClickListener(){
@凌驾
公共void onClick(视图v){
if(侦听器!=null)
onItemClicked(holder.getAdapterPosition());
}
});
}
@凌驾
public int getItemCount(){
返回mDataset.size();
}
公共void setListener(OnItemClickedListener侦听器){
this.listener=listener;
}
}
检查绑定视图的样式
public class CrimeListFragment extends Fragment {
private static final String SAVED_SUBTITLE_VISIBLE = "subtitle";
private static final int REQUEST_CRIME = 1;
private RecyclerView mRecyclerView;
private CrimeAdapter mCrimeAdapter;
private boolean mSubtitleVisible;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_crime_list, container, false);
mRecyclerView = (RecyclerView) view.findViewById(R.id.crime_recycler_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
if (savedInstanceState != null){
mSubtitleVisible = savedInstanceState.getBoolean(SAVED_SUBTITLE_VISIBLE);
}
updateUI();
return view;
}
private void updateUI() {
CrimeLab crimeLab = CrimeLab.get(getActivity());
List<Crime> crimes = crimeLab.getCrimes();
if (mCrimeAdapter == null) {
mCrimeAdapter = new CrimeAdapter(crimes);
mRecyclerView.setAdapter(mCrimeAdapter);
} else {
mCrimeAdapter.setCrimes(crimes);
mCrimeAdapter.notifyDataSetChanged();
}
updateSubtitle();
}
private class CrimeHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private TextView mTitleTextView;
private TextView mDateTextView;
private CheckBox mSolvedCheckBox;
private Crime mCrime;
public CrimeHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
mTitleTextView = (TextView) itemView.findViewById(R.id.list_item_crime_title_text_view);
mDateTextView = (TextView) itemView.findViewById(R.id.list_item_crime_date_text_view);
mSolvedCheckBox = (CheckBox) itemView.findViewById(R.id.list_item_crime_solved_checkbox);
}
public void bindCrime(Crime crime) {
mCrime = crime;
mTitleTextView.setText(mCrime.getTitile());
mDateTextView.setText(mCrime.getDate().toString());
mSolvedCheckBox.setChecked(mCrime.isSolved());
}
@Override
public void onClick(View v) {
/*Toast.makeText(getActivity(),mCrime.getTitile() + "clicked!", Toast.LENGTH_SHORT).show();*/
/*Intent for calling activity from fragment*/
/* Intent intent = new Intent(getActivity(), CrimeActivity.class);*/
/*Intent intent = CrimeActivity.newIntent(getActivity(),mCrime.getId());*/
Intent intent = CrimePagerActivity.newIntent(getActivity(), mCrime.getId());
/*startActivityForResult(intent,REQUEST_CRIME);*/
startActivity(intent);
}
}
private class CrimeAdapter extends RecyclerView.Adapter<CrimeHolder> {
private List<Crime> mCrimes;
public CrimeAdapter(List<Crime> crimes) {
mCrimes = crimes;
}
@Override
public CrimeHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
View view = layoutInflater.inflate(R.layout.list_item_crime, parent, false);
return new CrimeHolder(view);
}
@Override
public void onBindViewHolder(CrimeHolder holder, int position) {
Crime crime = mCrimes.get(position);
/*holder.mTextView.setText(crime.getTitile());*/
holder.bindCrime(crime);
}
@Override
public int getItemCount() {
return mCrimes.size();
}
public void setCrimes(List<Crime> crimes) {
mCrimes = crimes;
}
}
@Override
public void onResume() {
super.onResume();
updateUI();
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CRIME) {
}
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.fragment_crime_list, menu);
MenuItem subtitleItem = menu.findItem(R.id.menu_item_show_subtitle);
if (mSubtitleVisible){
subtitleItem.setTitle(R.string.hide_subtitle);
}else {
subtitleItem.setTitle(R.string.show_subtitle);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_item_new_crime:
Crime crime = new Crime();
CrimeLab.get(getActivity()).addCrime(crime);
Intent intent = CrimePagerActivity.newIntent(getActivity(), crime.getId());
startActivity(intent);
return true;
case R.id.menu_item_show_subtitle:
mSubtitleVisible = !mSubtitleVisible;
getActivity().invalidateOptionsMenu();
updateSubtitle();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void updateSubtitle(){
CrimeLab crimeLab = CrimeLab.get(getActivity());
int crimeCount = crimeLab.getCrimes().size();
String subtitle = getString(R.string.subtitle_format,crimeCount);
if (!mSubtitleVisible){
subtitle = null;
}
AppCompatActivity appCompatActivity = (AppCompatActivity)getActivity();
appCompatActivity.getSupportActionBar().setSubtitle(subtitle);
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(SAVED_SUBTITLE_VISIBLE,mSubtitleVisible);
}
}
公共类CrimeListFragment扩展了片段{
保存的私有静态最终字符串\u SUBTITLE\u VISIBLE=“SUBTITLE”;
私人静态最终int请求_犯罪=1;
私人回收视图mRecyclerView;
私家侦探mCrimeAdapter;
私有布尔msubtitlevible;
@凌驾
创建时的公共void(@Nullable Bundle savedInstanceState){
super.onCreate(savedInstanceState);
设置选项菜单(真);
}
@可空
@凌驾
创建视图时的公共视图(LayoutFlater充气机、@Nullable ViewGroup容器、@Nullable Bundle savedInstanceState){
视图=充气机。充气(R.layout.fragment\u crime\u list,container,false);
mRecyclerView=(RecyclerView)view.findViewById(R.id.crime\u recycler\u视图);
setLayoutManager(新的LinearLayoutManager(getActivity());
如果(savedInstanceState!=null){
msubtitlevible=savedInstanceState.getBoolean(保存的字幕可见);
}
updateUI();
返回视图;
}
私有void updateUI(){
CrimeLab CrimeLab=CrimeLab.get(getActivity());
列表犯罪=crimeLab.getCrimes();
if(mcrimedapter==null){
mCrimeAdapter=新的CrimeAdapter(犯罪);
mRecyclerView.setAdapter(mcrimedapter);
}否则{
mCrimeAdapter.setCrimes(罪行);
mcrimedapter.notifyDataSetChanged();
}
更新subtitle();
}
私有类CrimeHolder扩展了RecyclerView.ViewHolder实现了View.OnClickListener{
私有文本视图mTitleTextView;
私有文本视图mDateTextView;
私有复选框mSolvedCheckBox;
私人犯罪;
公共犯罪记录(查看项目视图){
超级(项目视图);
setOnClickListener(这个);
mTitleTextView=(TextView)itemView.findViewById(R.id.list\u item\u crime\u title\u text\u view);
mDateTextView=(TextView)itemView.findViewById(R.id.list\u item\u crime\u date\u text\u view);
mSolvedCheckBox=(复选框)itemviewbyd(R.id.list\u item\u crime\u solved\u CheckBox);
}
公共犯罪(刑事犯罪){
犯罪;
mTitleTextView.setText(mCrime.getTitile());
mDateTextView.setText(mcinite.getDate().toString());
mSolvedCheckBox.setChecked(mcinite.isSolved());
}
@凌驾
公共空间
@Override
public void onResume(){
super.onResume();
VerticalGridView defectGrid = grids.get(0);
RecyclerView.Adapter adapter = defectGrid.getAdapter();
defectGrid.smoothScrollToPosition(adapter.getItemCount()-1);
defectGrid.smoothScrollToPosition(0);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
final ViewHolder viewHolder = (ViewHolder) holder;
viewHolder.txtCategoryName.setText(categories.get(position).getStrCategory());
viewHolder.txtCategoryDefectTotal.setText(String.valueOf(categories.get(position).getTotalDefectsInCategory()));
}
grids.get(0).getAdapter().notifyDataSetChanged();
RecyclerView.Adapter adapter = recList.getAdapter();
recList.setAdapter(null);
recList.setAdapter(adapter);
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
mAdapter.notifyDataSetChanged();
}
});
<androidx.core.widget.NestedScrollView
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvGrid"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:nestedScrollingEnabled="false" />
</androidx.core.widget.NestedScrollView>