【问题标题】:How to handle orientation change and resource cleaning with mvvm如何使用 mvvm 处理方向更改和资源清理
【发布时间】:2018-01-08 00:02:55
【问题描述】:

我尝试通过数据绑定来理解 mvvm 架构。下面我写一个简单的例子:在片段开始时从网络加载数据。基本上,它有效。

但是我有一些问题。

1) 当方向改变时,片段从网络重新加载数据,因为loadFromNetwork() 调用onViewCreated。 ViewModel 没有重新创建,那么避免重新加载数据的正确解决方案是什么?我应该在 ViewModel 中实现“缓存”,还是在 View(Fragment) 中进行检查?

2) 当 Ui 销毁时,我们需要 dispose 网络操作。将这些清洁放在哪里(注意:subscribe 方法返回 Disposable)?

fragment_my.xml

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>
        <import type="android.view.View" />
        <import type="com.xxx.State" />
        <variable
            name="viewModel"
            type="com.xxx.MyViewModel" />
    </data>

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{viewModel.myPojo.data}" />
        <ProgressBar
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_gravity="center"
            android:visibility="@{viewModel.state == State.LOADING ? View.VISIBLE : View.GONE}" />
    </FrameLayout>

</layout>

MyViewModel.kt

class MyViewModel() : ViewModel() {

    val state = ObservableField(State.LOADING)

    val myPojo = ObservableField<MyPojo>()

    @Inject
    lateinit var netApi: NetworkApi

    init {
        Injector.getAppComponent().inject(this)
    }

    fun loadFromNetwork() {
        state.set(State.LOADING)

        netApi.getMyPojo().subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({
                    state.set(State.SUCCESS)
                    myPojo.set(it)
                }, {
                    state.set(State.ERROR)
                })
    }

}

MyFragment.kt

class MyFragment : Fragment(){

    private lateinit var mBinding: FragmentMyBinding
    private lateinit var mViewModel: MyViewModel

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        mViewModel = ViewModelProviders.of(this).get(MyViewModel::class.java)
    }

    override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        mBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_my, container, false)
        return mBinding.root
    }

    override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        mBinding.viewModel = mViewModel

        mViewModel.loadFromNetwork()
    }
}

【问题讨论】:

    标签: android mvvm android-lifecycle android-databinding kotlin-android-extensions


    【解决方案1】:

    您可以将数据保存到首选项或 sqlite 数据库,以避免每次都从网络获取。假设您不想这样做,我可以想到两个选择。首先,将数据存储到saveInstanceStateonDestroy 中的包并在onCreate 中读回数据的标准方法。其次,如果您有一个单一的“主要”活动或片段,我已经成功地将 ViewModel 设为静态并将其用作维护实例状态的一种方式。

    【讨论】:

      猜你喜欢
      • 2022-10-19
      • 2015-05-13
      • 2016-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-12
      • 2014-05-21
      • 2011-07-26
      相关资源
      最近更新 更多