美文网首页
2019-06-01 MvRxView和Epoxy刷新的问题

2019-06-01 MvRxView和Epoxy刷新的问题

作者: 兣甅 | 来源:发表于2019-06-01 15:05 被阅读0次

1.ViewModel可以通过下面两种方式创建:

通过(1)的方式会同步使用该ViewModel的所有页面,比如"关注"和"推荐"都使用下面(1)的方式,则会出现在关注页刷新数据,同时推荐页的数据也刷新了的问题,这种方式适用于两个一模一样的页面。如果不需要同时刷新该ViewModel的所有页面,请采用下面(2)的方式,即New的方式,New的方式只会在自己使用的地方调用才会刷新。两种方式如下:

(1)Mvrx自己的注入方式
//在fragment中使用时通过mvrx自己的注入方式使用需要实现这个
companion object : MvRxViewModelFactory<DynListViewModel, DynamicListState> {
  override fun create(
    viewModelContext: ViewModelContext,
    state: DynamicListState
  ): DynListViewModel {
      val repo by viewModelContext.app<App>().kodein.instance<FollowRepo>()
      return FollowViewModel(state, repo)
    return DynListViewModel(state)
  }
(2)New的方式
//采用new的方式
 private val viewModel: DynDetailViewModel by lazy {
    DynDetailViewModel()
  }

2.MvRxView的postInvalidate()调用问题

(1)默认在初始化的时候会采用ViewModel监听的方式调用,所以在数据改变后会自动刷新页面

viewModel.subscribe { postInvalidate() }

(2)在页面中监听数据回调

  override fun invalidate() {
    com.airbnb.mvrx.withState(viewModel) { state ->
      runOnUiThread {
        ......
      }
    }
  }

(3)在Epoxy中监听,分2部

  //1.刷新Controller
  override fun invalidate() {
    epoxyController.requestModelBuild()
  }
  //2.在Controller中获取数据
  private val epoxyController = MvRxEpoxyController {
    com.airbnb.mvrx.withState(viewModel) { state ->
    }
  }

3.Epoxy数据变化刷新问题

(1)当数据变化后,如果会调用到ViewModel中的copy方法,则不需要在变化的地方调用postInvalidate()方法,内部会通过数据监听方式触发subscribe的invalidate去刷新Controller

//1. Controller的item代码
 dynCommentHeaderItem {
        id("comment_header_top")
        totalSize(state.totalSize)
        sortByHot(state.sortByHot)
        onClickSort {
          viewModel.changeSortByHot(dynDetailSticky.visibility == View.VISIBLE)//调用排序的代码
        }
      }
//2.ViewModel中的刷新代码
  fun changeSortByHot(needScrollTop: Boolean) {
    withState { state ->
      setState {
        copy(
          dynamicBean = state.dynamicBean,
          totalSize = state.totalSize,
          sortByHot = !state.sortByHot,
          needScrollTop = needScrollTop,
          commentList = sortData(state.commentList, !state.sortByHot)
        )
      }
    }
  }

(2)不采用数据监听,直接修改数据后刷新

        //Controller的item代码
        dynCommentItem {
          id("comment_" + it.id)
          dynId(dynId)
          commentBean(it)
          onClickReply { syncOpenKeyboard(true, it) }
          onClickPraise { bean ->
            val newBean = bean.copy(isPraise = !bean.isPraise)
            if (!newBean.isPraise) {
              newBean.praiseNum += -1
              mContext.toast("取消点赞")
            } else {
              newBean.praiseNum += 1
              mContext.toast("点赞")
            }
            Collections.replaceAll(state.commentList, bean, newBean)//1.更换数据
            postInvalidate()//2.直接调用刷新
          }
          onItemClick { showCopyDialog(it) }
        }

(3)更换数据的两种方式,由于Epoxy更换数据后可能出现不刷新的问题(因为id一致),所以需要采用copy的方式刷新

//1.Collections.replaceAll
Collections.replaceAll(beanList, oldBean, oldBean.copy())
//2.直接采用新的数据替换旧数据
beanList.set(beanList.indexOf(oldBean),oldBean.copy())

4.一个简单的viewmodel.kt代码

data class SettingState(
  val cacheSize: Long = 0,
  val request: Async<Boolean> = Uninitialized
) : MvRxState

class SettingViewModel(
  state: SettingState = SettingState()
) : MvRxViewModel<SettingState>(state) {
  ......
}

5.页面中引用

class SettingActivity : CommTitleActivity(), MvRxView {

  private val viewModel: SettingViewModel by lazy {
    SettingViewModel()
  }

  override fun initData() {
    viewModel.subscribe { postInvalidate() }
  }

  override fun invalidate() {
    com.airbnb.mvrx.withState(viewModel) { state ->
      runOnUiThread {
        ......
      }
    }
  }
}

相关文章

网友评论

      本文标题:2019-06-01 MvRxView和Epoxy刷新的问题

      本文链接:https://www.haomeiwen.com/subject/hgxatctx.html