【问题标题】:Android data binding with custom adapter使用自定义适配器的 Android 数据绑定
【发布时间】:2020-11-11 14:23:04
【问题描述】:

我正在尝试将 Android's Data Binding features 与自定义适配器和 ListView 一起使用。我无法覆盖自定义适配器的 getView 方法:

public class ChecksAdapter extends ArrayAdapter<Check> {

    public ChecksAdapter(Context context, ObservableList<Check> checks) {
        super(context, R.layout.check, checks);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        CheckBinding binding = DataBindingUtil.inflate(
                LayoutInflater.from(getContext()),
                R.layout.check, parent, false);
        binding.setCheck(this.getItem(position));

        // Return what?
    }
    
}

所以我的问题是:

  • 我应该从哪里获得应该返回的View 元素?或者换句话说,如何将对象绑定到膨胀/转换的视图?
  • 如何在使用数据绑定时重用convertView?
  • 这是实现此功能的正确方法吗?该指南对 ListViews 不是很清楚

这是指南中 ListViews 的唯一参考:

如果您在 ListView 或 RecyclerView 适配器中使用数据绑定项,您可能更喜欢使用:

   ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup, false);
   //or
   ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false);

【问题讨论】:

    标签: android android-databinding


    【解决方案1】:

    您应该执行以下操作以实现平滑滚动..

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        CheckBinding binding;
        if(convertView == null) {
            binding = DataBindingUtil.inflate(
                    LayoutInflater.from(getContext()),
                    R.layout.check, parent, false);
            convertView = binding.getRoot();
        }
        else {
            binding = (CheckBinding) convertView.getTag();
        }
    
        binding.setCheck(this.getItem(position));
        convertView.setTag(binding);
        return convertView;
    }
    

    【讨论】:

    • 我不知道为什么,但是当我使用光标适配器时这对我不起作用
    • @sergi 你为什么要检查 convertView 是否为空?
    • @Thalatta 第一次显示该行时,convertView.getTag() 将返回一个 null 对象,因为它从未被初始化。 if 分支中的代码只会在第一次显示可见行时作为初始化执行。滚动时,将到达 else 分支。
    【解决方案2】:

    根据this,你应该返回binding.getRoot()。

    View getRoot ()
    

    返回布局文件中与 捆绑。如果此绑定用于合并布局文件,则将返回 合并标签中的第一个根。

    【讨论】:

      【解决方案3】:

      为了完成这里是 kotlin 变体:

          val binding = convertView?.tag as? CheckBinding ?: CheckBinding.inflate(layoutInflater, parent, false)
          binding.check = this.getItem(position)
          binding.root.tag = binding
      
          return binding.root
      

      【讨论】:

        【解决方案4】:

        推荐方式

        使用生成的 Binding 类而不是 DataBindingUtil 类。见Documentation.

        如果您在 Fragment、ListView 或 RecyclerView 适配器,您可能更喜欢使用 inflate() 的方法 绑定类

        使用

        binding = CheckBinding.inflate(this, parent, false);
        

        而不是

        binding = DataBindingUtil.inflate(
                        LayoutInflater.from(getContext()),
                        R.layout.check, parent, false);
        

        其他代码与@sergi 相同

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            CheckBinding binding;
            if(convertView == null) {
                binding = CheckBinding.inflate(this, parent, false);
                convertView = binding.getRoot();
            }
            else {
                binding = (CheckBinding) convertView.getTag();
            }
        
            binding.setCheck(this.getItem(position));
            convertView.setTag(binding);
            return convertView;
        }
        

        【讨论】:

        • 当我使用这种方法时,我经常收到提示 R.layout.check 似乎未使用的 lint 警告。因此,我更喜欢使用DataBindingUtil
        【解决方案5】:
        ItemTickFilterBinding mFilterBinding;
        
            if (convertView==null) {
                mFilterBinding= DataBindingUtil.inflate(
                        LayoutInflater.from(mContext),
                        R.layout.item_tick_filter, parent, false);
                convertView.setTag(mFilterBinding);
            }
            else {
                mFilterBinding=(ItemTickFilterBinding)convertView.getTag();
            }
        

        【讨论】:

        • 在基本适配器的getView方法中。mFilterBinding是listrow布局的实例,你应该在转换视图上设置标签并进入else部分。
        【解决方案6】:

        DataBindingUtil 会将 ViewDataBinding 对象保存到 view.tag 中,以便稍后通过 DataBindingUtil.getBinding(convertView) 检索它

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            return getViewForResource(mResourceId, position, convertView, parent);
        }
        
        @Override
        public View getDropDownView(int position, View convertView, ViewGroup parent) {
            return getViewForResource(mDropDownResourceId, position, convertView, parent);
        }
        
        public View getViewForResource(int resourceId, int position, View convertView, ViewGroup parent) {
            final ViewDataBinding binding = (convertView != null) ? DataBindingUtil.getBinding(convertView) : DataBindingUtil.inflate(mLayoutInflater, resourceId, parent, false);
            binding.setVariable(BR.viewModel, getItem(position));
            return binding.getRoot();
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-01-01
          • 2021-07-28
          • 2018-01-15
          • 2021-02-16
          • 2017-07-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多