android - 将 ViewModel 与 ViewPagers 相结合

标签 android android-viewpager android-architecture-components android-viewmodel

我正在制作一个简单的应用程序,它包含一个计时器列表并允许用户通过 ViewPager 在这些计时器之间滚动。 Android 架构组件原则在这里生效:ViewModel 保存应用程序的状态,而 Fragments/Activities 仅处理 UI 交互。

在这种情况下,已经制作了自定义的 ViewPager 和 FragmentStatePagerAdapter。我的问题是,让 ViewPager/adapter 响应 ViewModel 中的变化的最佳方式是什么?

下面的当前代码工作正常,但是有更好的方法吗?目前,ViewPager 和 Adapter 都需要引用 ViewModel,这感觉与 MVVM 应该实现的相反。

ViewPager

    class VerticalTimerViewPager(context: Context, attributeSet: AttributeSet): ViewPager(context, attributeSet){

    var homeViewModel: HomeViewModel?=null

    init {
        setPageTransformer(true, VerticalPageTransformer())
    }


    override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {

        ev ?: return false
        val intercepted =  super.onInterceptTouchEvent(swapXYOnMotionEvent(ev))
            swapXYOnMotionEvent(ev)
        return intercepted
    }

    override fun onTouchEvent(ev: MotionEvent?): Boolean {
        homeViewModel ?: throwNoViewModelException()
        when(ev?.action){
            MotionEvent.ACTION_DOWN -> homeViewModel?.onSwipeDown()
            MotionEvent.ACTION_UP -> homeViewModel?.onSwipeUp()
        }
        return super.onTouchEvent(swapXYOnMotionEvent(ev ?: return false))
    }

    private fun swapXYOnMotionEvent(motionEvent: MotionEvent): MotionEvent{
        with(motionEvent){
            val newX = (y/height)*width
            val newY = (x/width) * height
            setLocation(newX, newY)
        }
        return motionEvent
    }

    private fun throwNoViewModelException():Boolean{
        throw RuntimeException("${this.javaClass.simpleName}: HomeViewModel must be set by setting the variable homeViewModel")
    }
}

FragmentStatePagerAdapter

 class VerticalTimerViewPager(context: Context, attributeSet: AttributeSet): ViewPager(context, attributeSet){

    var homeViewModel: HomeViewModel?=null

    init {
        setPageTransformer(true, VerticalPageTransformer())
    }


    override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {

        ev ?: return false
        val intercepted =  super.onInterceptTouchEvent(swapXYOnMotionEvent(ev))
            swapXYOnMotionEvent(ev)
        return intercepted
    }

    override fun onTouchEvent(ev: MotionEvent?): Boolean {
        homeViewModel ?: throwNoViewModelException()
        when(ev?.action){
            MotionEvent.ACTION_DOWN -> homeViewModel?.onSwipeDown()
            MotionEvent.ACTION_UP -> homeViewModel?.onSwipeUp()
        }
        return super.onTouchEvent(swapXYOnMotionEvent(ev ?: return false))
    }

    private fun swapXYOnMotionEvent(motionEvent: MotionEvent): MotionEvent{
        with(motionEvent){
            val newX = (y/height)*width
            val newY = (x/width) * height
            setLocation(newX, newY)
        }
        return motionEvent
    }

    private fun throwNoViewModelException():Boolean{
        throw RuntimeException("${this.javaClass.simpleName}: HomeViewModel must be set by setting the variable homeViewModel")
    }
}

在 Activity onCreate() 中调用的实例化方法

    private fun setupPagerAdapter() {
    val pagerAdapter = TimerSlidePagerAdapter(viewModel = viewModel, fragmentManager = supportFragmentManager)
    with(pager){
        adapter = pagerAdapter
        homeViewModel = viewModel
    }
}

最佳答案

看起来您正在使用 ViewModel 从您的适配器onTouchEvent(ev: MotionEvent?) 进行通信> & 查看寻呼机,如果你想让你的适配器和查看寻呼机独立于 ViewModel,我建议你采用以下方式:

  1. 创建一个具有方法onSwipeDown() & onSwipeUp() 的接口(interface)(或者为 ViewModel 创建任意 N 个方法)

  2. 在您的 View 分页器和适配器中使用此接口(interface)对象而不是 ViewModel

  3. 为您的 ViewModel 实现此接口(interface)(这将在 ViewModel 中公开接口(interface)方法)

  4. 将您的界面转换到 ViewModel,您将在其中将 ViewModel 传递给适配器和查看寻呼机。

瞧!您已经使您的适配器和 View 寻呼机独立于 ViewModel 的直接引用。

关于android - 将 ViewModel 与 ViewPagers 相结合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52595716/

相关文章:

android - 有没有办法在 react-native 应用程序上显示 CPU 和内存使用情况?

android - com.android.support :support-v4 has different version for the compile

android - 初始初始化组织

java - “海拔”不在 ViewPager 中显示阴影

java - 在 ViewPager fragment 中更新 TextView

android - 使用 LiveData 在 ImageView 上使用 DataBinding 时出现 IllegalArgumentException

java - 更新 LiveData 返回的对象属性

java - 安卓 : How to save data (Intent's Data)

android - 更改可见性后 ViewPager 无法滑动

安卓架构组件 : How to insert repository parameter