ButterKnife同时绑定FloatingActionButton与AlertDialog报错求解
这个问题我开发时也踩过坑!核心问题在于你把对话框专属的EditText的@BindView注解直接写在了Activity类里——当你在onCreate中调用ButterKnife.bind(this)时,ButterKnife会扫描当前类所有的@BindView注解,试图在Activity的布局里找到对应的控件,但这三个EditText只存在于对话框的布局中,自然会找不到而抛出异常。
这里有两种优雅的解决方案:
方案一:使用内部ViewHolder类绑定对话框控件
把对话框的控件绑定逻辑抽成一个独立的内部ViewHolder,让ButterKnife只在这个Holder里绑定对话框的视图,和Activity的绑定完全分离。
步骤1:创建内部ViewHolder类
在你的Activity中添加一个静态内部类,专门用来管理对话框的控件:
static class DialogInputHolder { @BindView(R.id.id_edit_text) EditText idEditText; @BindView(R.id.name_edit_text) EditText nameEditText; @BindView(R.id.desc_edit_text) EditText descEditText; // 构造函数中完成绑定 DialogInputHolder(View dialogView) { ButterKnife.bind(this, dialogView); } }
步骤2:修改showAlertDialog方法
不再绑定Activity本身,而是绑定上面的ViewHolder:
public void showAlertDialog(){ AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this); LayoutInflater inflater = this.getLayoutInflater(); View dialogView = inflater.inflate(R.layout.dialog_layout, null); // 绑定对话框的ViewHolder DialogInputHolder inputHolder = new DialogInputHolder(dialogView); // 现在可以通过inputHolder访问对话框的输入框,比如: // inputHolder.idEditText.setText("默认内容"); dialogBuilder.setView(dialogView); AlertDialog dialog = dialogBuilder.create(); dialog.show(); }
步骤3:正常绑定Activity布局
在Activity的onCreate中正常绑定,这时候只会处理Activity布局里的控件(比如你的FloatingActionButton):
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.your_activity_layout); // 替换成你的Activity布局文件 ButterKnife.bind(this); // 这里只会绑定Activity布局中的控件,不会再找对话框的EditText了 }
注意:一定要把原来Activity类里声明的那三个@BindView的EditText变量删掉,避免干扰!
方案二:直接用findViewById获取对话框控件
如果不想写额外的ViewHolder类,也可以直接在对话框视图中用findViewById获取控件,这种方式更直接,适合简单场景:
public void showAlertDialog(){ AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this); LayoutInflater inflater = this.getLayoutInflater(); View dialogView = inflater.inflate(R.layout.dialog_layout, null); // 直接从对话框视图中查找控件 EditText idEditText = dialogView.findViewById(R.id.id_edit_text); EditText nameEditText = dialogView.findViewById(R.id.name_edit_text); EditText descEditText = dialogView.findViewById(R.id.desc_edit_text); // 后续操作输入框... dialogBuilder.setView(dialogView); AlertDialog dialog = dialogBuilder.create(); dialog.show(); }
这种方式不需要修改Activity的onCreate绑定逻辑,同样要记得删掉Activity里的那三个@BindView变量。
两种方案里,我更推荐第一种ViewHolder的方式,符合ButterKnife的最佳实践,代码更整洁,也方便后续扩展对话框的控件。
内容的提问来源于stack exchange,提问作者Sidharth Yatish

