【问题标题】:AirBnb Epoxy - Views are duplicated instead of replacedAirBnb Epoxy - 视图被复制而不是被替换
【发布时间】:2020-12-10 08:29:43
【问题描述】:

我正在根据从服务器获取的 JSON 响应呈现表单。

我的用例包括监听单选按钮的点击,根据单选按钮的选择切换某些文本字段的可见性,以及使用可见的 textView 刷新布局。

预期的输出应该是用现在可见的 textView 更新同一个视图,但我现在看到同一个表单两次,第一次是默认状态,第二次是更新状态。

我是否以某种方式创建了一个全新的model_ 类并将其传递给控制器​​?我只想更改现有模型的布尔字段并更新视图。

我的模型课

@EpoxyModelClass(layout = R.layout.layout_panel_input)
abstract class PanelInputModel(
    @EpoxyAttribute var panelInput: PanelInput,
    @EpoxyAttribute var isVisible: Boolean,
    @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var context: Context,
    @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var textChangedListener: InputTextChangedListener,
    @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var radioButtonSelectedListener: RadioButtonSelectedListener,
    @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash) var validationChangedListener: ValidationChangedListener
) : EpoxyModelWithHolder<PanelInputModel.PanelInputHolder>() {

    @EpoxyAttribute var imageList = mutableListOf<ImageInput>()

    override fun bind(holder: PanelInputHolder) {
        val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
        generateViews(holder, inflater, panelInput.elements) // Generates textViews, radioButtons, etc, based on ElementType enum inside Panel input
    }

   fun generateRadioButtonView(element: Element) {
        // Created a custom listener and calling its function
        radioButtonSelectedListener.radioButtonSelected(chip.id, chip.text.toString())
   }

  fun generateTextView() {
     // Show/hide textView based on isVisible value
  }

我的控制器类

class FormInputController(
    var context: Context,
    var position: Int, // Fragment Position in PagerAdapter
    var textChangedListener: InputTextChangedListener,
    var radioButtonSelectedListener: RadioButtonSelectedListener,
    var validationChangedListener: ValidationChangedListener
) : TypedEpoxyController<FormInput>() {

    override fun buildModels(data: FormInput?) {
        val panelInputModel = PanelInputModel_(
            data as PanelInput,
            data.isVisible,
            context,
            textChangedListener,
            radioButtonSelectedListener,
            validationChangedListener
        )
        panelInputModel.id(position)
        panelInputModel.addTo(this)
    }
}

我的片段实现了单选按钮选中的侦听器,修改了formInput.isVisible = true 并调用了formInputController.setData(componentList)

请帮帮我,谢谢!

【问题讨论】:

    标签: android android-recyclerview epoxy epoxy-modelview


    【解决方案1】:

    我认为您没有正确使用 Epoxy,这不是应该的。

    1. 首先,让我们从 Holder 开始:您不应该在 bind/unbind 中膨胀视图,只需在此处设置视图即可。此外,视图会根据您在 R.layout.layout_panel_input 指定的布局文件为您膨胀,因此根本不需要膨胀。

    您应该将其复制到您的项目中: https://github.com/airbnb/epoxy/blob/master/kotlinsample/src/main/java/com/airbnb/epoxy/kotlinsample/helpers/KotlinEpoxyHolder.kt

    并以这种方式创建您的持有人:

    class PanelInputHolder : KotlinHolder() {
    
        val textView by bind<TextView>(R.id.your_text_view_id)
        val button by bind<Button>(R.id.your_button_id)
    }
    
    1. 让我们转到您的模型类:您应该从构造函数中删除这些变量,因为它们将成为注释处理器创建实际类的参考。 另外,不要在注释中设置布局资源,因为将来不允许这样做。

    像这样:

    @EpoxyModelClass
    class PanelInputModel : EpoxyModelWithHolder<PanelInputHolder>() {
    
        @EpoxyAttribute
        lateinit var text: String
        @EpoxyAttribute(DoNotHash)
        lateinit var listener: View.OnClickListener
    
        override fun getDefaultLayout(): Int {
            return R.layout.layout_panel_input
        }
    
        override fun bind(holder: PanelInputHolder) {
    
            // here set your views
            holder.textView.text = text
            holder.textView.setOnClickListener(listener)
        }
    
        override fun unbind(holder: PanelInputHolder) {
    
            // here unset your views
            holder.textView.text = null
            holder.textView.setOnClickListener(null)
        }
    }
    
    1. 在控制器内部而不是模型内部循环您的数据:
    
    class FormInputController : TypedEpoxyController<FormInput>() {
        
        
        override fun buildModels(data: FormInput?) {
        
            data?.let {
    
                // do your layout as you want, with the models you specify
                // for example a header
            
                PanelInputModel_()
                    .id(it.id)
                    .text("Hello WOrld!")
                    .listener { // do something here }
                    .addTo(this)
            
                // generate a model per item
                it.images.forEach {
                
                    ImageModel_()
                        .id(it.imageId)
                        .image(it)
                        .addTo(this)
                }
            }
        }
    }
    

    在选择您的 id 时,请记住 Epoxy 会跟踪这些并在 attrs 更改时进行更新,因此不要使用位置,而是使用不会重复的唯一 id。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-08
      相关资源
      最近更新 更多