마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

Epoxy 리사이클러뷰의 상태를 유지하는 방법.

0 추천

만드려는 UI가 확장가능한 중첩 리사이클러뷰가 필요할것 같아서, 그냥 리사이클러뷰로 구현을 할까하다가..

그냥 편하게 Epoxy를 사용했습니다. 

 

현재 아이템 각각을을 접었다가 펼쳤다가하는것은 문제가 없는데

아이템을 펼친상태에서 스크롤을하면 두가지 에러가 발생합니다.

 

1. 

Epoxy attribute fields on a model cannot be changed once the model is added to a controller.
Check that these fields are not updated, or that the assigned objects are not mutated, outside of the buildModels method.
The only exception is if the change is made inside an Interceptor callback.
 Consider using an interceptor if you need to change a model after it is added to the controller and before it is set on the adapter.
If the model is already set on the adapter then you must call requestModelBuild instead to recreate all models.

이라는 에러인데요. https://github.com/airbnb/epoxy/issues/1115#issuecomment-871174543 여기를 참고해서 해결했습니다. 좀 찝찝한 방법이긴하지만요..

override fun buildModels() {
    data.forEachIndexed { index, s ->
        ParentDataModel_()
            .id(index)
            .title(s.workout)
            .list(s.list)
            .onBind { model, view, position ->
                requestModelBuild()
            }
            .addTo(this)
    }
}

.onBind { requestModelBuilds() } 를 추가해주니 위 문제는 해결 됐습니다. 옳은 방법인지는 모르겠습니다.

그런데 두번째 문제는

 

2. 

 

 

첫번째 사진: 기본

두번째 사진: 아이템을 펼친상태

세번째 상태: 스크롤을 내렸다가 올린 상태

입니다.

정상적으로라면 세번째 사진에서 첫번째 아이템이 펼쳐져있는 상태가 유지되어야하는데

유지가 되지않습니다.. 이걸 어떻게 해결하면 좋나요? 

새로운 라이브러리를 편하자고 썼는데 또 문제에 부딪히고 정보는 더 없어서 힘드네요.. 기본 리사이클러뷰도 똑같을지 모르겠지만요..

--

부모 컨트롤러와 모델 코드만 일단 올리겠습니다..

Controller

class ParentEpoxyController : EpoxyController() {
    private lateinit var data : List<ParentItem>

    override fun buildModels() {
        data.forEachIndexed { index, s ->
            ParentDataModel_()
                .id(index)
                .title(s.workout)
                .list(s.list)
                .onBind { model, view, position ->
                    requestModelBuild()
                }
                .addTo(this)
        }
    }

    fun setItem(items : List<ParentItem>){
        data = items
        requestModelBuild()
    }
}

 

Model

@EpoxyModelClass(layout = R.layout.item_data)
abstract class ParentDataModel : EpoxyModelWithHolder<ParentDataModel.ItemViewHolder>() {

    @EpoxyAttribute
    lateinit var title: String

    @EpoxyAttribute
    lateinit var list: List<String>

    @EpoxyAttribute
    var expanded: Boolean = false

    override fun bind(holder: ItemViewHolder) {
        super.bind(holder)
        holder.tv.text = title

        val controller = ChildEpoxyController()
        holder.nestedRV.adapter = controller.adapter
        controller.setItem(list)

        holder.expandBtn.setOnClickListener {
            if(expanded) {
                holder.nestedRV.visibility = View.GONE
            }
            else
                holder.nestedRV.visibility = View.VISIBLE
            expanded = !expanded
            controller.requestModelBuild()
        }
    }

    class ItemViewHolder : KotlinEpoxyHolder() {
        val tv by bind<TextView>(R.id.tv)
        val nestedRV by bind<RecyclerView>(R.id.nested_rv)
        val expandBtn by bind<TextView>(R.id.expanded)
    }
}

 

codeslave (3,940 포인트) 님이 2022년 7월 11일 질문

답변 달기

· 글에 소스 코드 보기 좋게 넣는 법
· 질문에 대해 추가적인 질문이나 의견이 있으면 답변이 아니라 댓글로 달아주시기 바랍니다.
표시할 이름 (옵션):
개인정보: 당신의 이메일은 이 알림을 보내는데만 사용됩니다.
스팸 차단 검사:
스팸 검사를 다시 받지 않으려면 로그인하거나 혹은 가입 하세요.
...