如何使用Data Binding在ListView中展示输入结果
Data Binding实现自定义ArrayAdapter输入文本不显示问题修复
核心问题点
- 点击按钮新增列表项时,错误读取新建空Model的null值赋值,没有获取EditText绑定的用户输入内容
- 每次点击都重新创建Adapter实例,且ViewModel的adapter字段未声明可观察,Data Binding无法感知适配器变更
- 自定义Adapter的getView方法存在空指针风险,且错误调用父类getView方法返回默认视图,没有使用Data Binding渲染的列表项布局
- Model类未实现数据观察接口,双向绑定的文本同步存在异常
分步修复方案
1. 修正MainActivity点击事件逻辑
初始化时一次性创建Adapter实例,点击事件中正确读取输入内容、新增列表项后通知数据刷新即可,无需重复创建Adapter:
private Model model = new Model(); private Handlers handlers = new Handlers(); private ViewModel viewModel = new ViewModel(model); private ArrayList<Model> listItem = new ArrayList<>(); ActivityMainBinding mainBinding = DataBindingUtil.setContentView(this,R.layout.activity_main); // 初始化阶段创建适配器,不要在点击事件中重复创建 viewModel.setAdapter(new CustomAdapter(MainActivity.this, listItem)); handlers.setOnClickListener(new MyView.onClickListener() { @Override public void onDamn(Model inputModel) { Model newItem = new Model(); // 正确获取输入框绑定的用户输入内容 newItem.setText(inputModel.getText()); listItem.add(newItem); // 通知适配器数据刷新 viewModel.getAdapter().notifyDataSetChanged(); } }); mainBinding.setModel(model); mainBinding.setHandlers(handlers); mainBinding.setViewModel(viewModel);
2. 修正ViewModel的adapter字段可观察配置
给adapter字段添加@Bindable注解,赋值时通知属性变更,保证Data Binding能识别到适配器的绑定:
package com.example.list; import androidx.databinding.BaseObservable; import androidx.databinding.Bindable; public class ViewModel extends BaseObservable { private Model model; public ViewModel(Model model){ this.model = model; } public void setModelText(String text){ model.setText(text); notifyPropertyChanged(BR.modelText); } @Bindable public String getModelText(){ return model.getText(); } private CustomAdapter adapter; public void setAdapter(CustomAdapter adapter) { this.adapter = adapter; notifyPropertyChanged(BR.adapter); } @Bindable public CustomAdapter getAdapter() { return adapter; } }
3. 修正CustomAdapter的getView渲染逻辑
复用列表项时通过Tag获取已有的Binding实例避免空指针,移除父类getView调用,直接返回Data Binding渲染的视图,添加executePendingBindings保证数据及时刷新:
package com.example.list; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.databinding.DataBindingUtil; import com.example.list.databinding.ActivityItemBinding; import java.util.ArrayList; public class CustomAdapter extends ArrayAdapter<Model> { private ArrayList<Model> listItem; public CustomAdapter(Context context, ArrayList<Model> listItem){ super(context,0,listItem); this.listItem = listItem; } @NonNull @Override public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) { ActivityItemBinding itemBinding; Model model = listItem.get(position); if (convertView == null){ itemBinding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()),R.layout.activity_item,parent,false); convertView = itemBinding.getRoot(); convertView.setTag(itemBinding); } else { itemBinding = (ActivityItemBinding) convertView.getTag(); } ViewModel itemViewModel = new ViewModel(model); itemViewModel.setModelText(model.getText()); itemBinding.setViewModel(itemViewModel); // 立即执行绑定,避免列表滑动时数据错乱 itemBinding.executePendingBindings(); return convertView; } @Override public int getCount() { return listItem.size(); } @Nullable @Override public Model getItem(int position) { return listItem.get(position); } @Override public long getItemId(int position) { return position; } }
4. 修正Model类的双向绑定支持
让Model继承BaseObservable,给text字段添加可观察注解,保证双向绑定数据同步正常:
package com.example.list; import androidx.databinding.BaseObservable; import androidx.databinding.Bindable; public class Model extends BaseObservable { private String text; @Bindable public String getText() { return text; } public void setText(String text) { this.text = text; notifyPropertyChanged(BR.text); } }
修复后EditText输入的内容会在点击按钮后正常添加到ListView中展示,不会出现空值、不刷新的问题。
内容的提问来源于stack exchange,提问作者Aloyrd Vey
相关产品推荐
相关产品推荐

