长按RecyclerView条目设置按钮可见出现空对象引用错误如何解决
报错原因
- 控件查找范围错误:你需要操作的
btnRemove定义在activity_main布局中,但你在ViewHolder构造方法中是从RecyclerView子项布局R.layout.stock_row里执行findViewById查找,子项布局不存在该id的控件,所以btnRemove始终为null,调用setVisibility就会抛出空指针异常。 - 额外逻辑错误:
StockAdapter构造方法中直接new MainActivity()的写法完全不符合Android规范,Activity实例必须由Android系统创建,手动new出来的实例没有绑定任何布局和上下文,完全不可用。
修复方案
第一步:修改MainActivity代码,持有按钮实例并提供调用方法
public class MainActivity extends AppCompatActivity { private DBHandler db; Button btnAddItem; // 新增声明移除按钮 Button btnRemove; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); RecyclerView stockView = findViewById(R.id.rvStock); // 找到activity_main布局里的移除按钮,初始设为不可见 btnRemove = findViewById(R.id.btnRemove); btnRemove.setVisibility(View.INVISIBLE); LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this); stockView.setLayoutManager(linearLayoutManager); stockView.setHasFixedSize(true); db = new DBHandler(this); ArrayList<Stock> allStock = db.getAllStock(); if (allStock.size() > 0) { stockView.setVisibility(View.VISIBLE); StockAdapter stockAdapter = new StockAdapter(this, allStock); stockView.setAdapter(stockAdapter); } else { stockView.setVisibility(View.GONE); Toast.makeText(this, "No Items!", Toast.LENGTH_LONG).show(); } btnAddItem = findViewById(R.id.btnAdd); btnAddItem.setOnClickListener(v -> { addNewItem(); }); } // 新增供Adapter调用的显示按钮方法 public void showRemoveBtn() { btnRemove.setVisibility(View.VISIBLE); } protected void addNewItem() { Intent i = new Intent(MainActivity.this, AddNewItem.class); startActivity(i); } }
第二步:修改StockAdapter代码,调整长按触发逻辑
public class StockAdapter extends RecyclerView.Adapter<StockAdapter.ViewHolder> { private Context context; private ArrayList<Stock> listStock; private ArrayList<Stock> mArrayList; private DBHandler db; private MainActivity mainActivity; StockAdapter(Context context, ArrayList<Stock> listStock) { this.context = context; this.listStock = listStock; this.mArrayList = listStock; db = new DBHandler(context); // 直接把传入的context强转为MainActivity实例,不需要手动new mainActivity = (MainActivity) context; } @NonNull @Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { LayoutInflater inflater = LayoutInflater.from(parent.getContext()); View stockView = inflater.inflate(R.layout.stock_row, parent, false); return new ViewHolder(stockView); } @Override public void onBindViewHolder(ViewHolder holder, int position) { final Stock stock = listStock.get(position); holder.tvItem.setText(stock.getItem()); holder.tvCondition.setText(stock.getCondition()); holder.tvQuantity.setText(String.valueOf(stock.getQuantity())); holder.tvLocation.setText(stock.getLocation()); holder.tvCategory.setText(stock.getCategory()); } @Override public int getItemCount() { return listStock.size(); } class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener { final TextView tvItem; final TextView tvCondition; final TextView tvQuantity; final TextView tvLocation; final TextView tvCategory; // 移除子项中不存在的btnRemove声明 View stockView; ViewHolder(View stockView) { super(stockView); this.stockView = stockView; stockView.setOnClickListener(this); stockView.setOnLongClickListener(this); tvItem = stockView.findViewById(R.id.tvItem); tvCondition = stockView.findViewById(R.id.tvCondition); tvQuantity = stockView.findViewById(R.id.tvQuantity); tvLocation = stockView.findViewById(R.id.tvLocation); tvCategory = stockView.findViewById(R.id.tvCategory); // 移除从子项布局查找btnRemove的逻辑 } @Override public void onClick(View stockView) { } @Override public boolean onLongClick(View stockView) { // 调用MainActivity暴露的方法显示按钮 mainActivity.showRemoveBtn(); Toast.makeText(context, "long pressed", Toast.LENGTH_SHORT).show(); return false; } } }
内容的提问来源于stack exchange,提问作者rholmes97
相关产品推荐
相关产品推荐

