使用视图模型时不保留方向更改

Posted

技术标签:

【中文标题】使用视图模型时不保留方向更改【英文标题】:Orientation change is not preserved while using viewmodel 【发布时间】:2022-01-05 04:56:19 【问题描述】:

MVVM 清洁架构的新手。构建一个具有由回收器视图组成的单屏幕的应用程序。数据是通过改造获取的。根据文档,ViewModel 能够承受配置更改,但在我的情况下,当我将方向从纵向更改为横向时,它不起作用。不知道这个问题,请指教

**NewsViewModel.Kt**   

import android.util.Log
import androidx.lifecycle.*
import com.example.recyclerviewjsonarray.model.NewsList
import com.example.recyclerviewjsonarray.network.remote.RetrofitInstanceDto
import com.example.recyclerviewjsonarray.network.remote.RetrofitServiceDto
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

private const val TAG ="NewsViewModel"

//viewmodel for handling clean archietecture
 class NewsViewModel : ViewModel() 
    //Mutable live data for the news list
  private val _newsMutableLiveData: MutableLiveData<NewsList> = MutableLiveData()

  val newsMutableLiveData : LiveData<NewsList> get() =
      _newsMutableLiveData

    //viewmodel will observe the latest updated data with the help of mutable live data
   fun newsListObserver(): LiveData<NewsList> 
       return newsMutableLiveData
  

    /* making an api call using viewmodel scope (custom coroutines scope can be used as well)
       launch is like a builder . Here it is launching Dispatcher.IO for memory intensive operation
       Now inside we will create synchronized retrofit instance and fetch the response
       in the form of getDataFromApi() with a delay of 2 seconds respectively
       post value is called lastly for setting the value from a background thread */


    fun getDataFromApi() 
        Log.i(TAG,"init")
        viewModelScope.launch(Dispatchers.IO) 
            val retrofitInstance = RetrofitInstanceDto.getRetrofitInstance().create(RetrofitServiceDto::class.java)
            val response = retrofitInstance.getDataFromApi()
            delay(1500)
            _newsMutableLiveData.postValue(response)
        
    


**NewsListFragment.kt**


import android.os.Bundle
import android.util.Log

import android.view.*
import androidx.fragment.app.Fragment
import android.widget.Toast

import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.recyclerviewjsonarray.R
import com.example.recyclerviewjsonarray.databinding.FragmentNewsListBinding
import com.example.recyclerviewjsonarray.model.NewsList
import kotlinx.android.synthetic.main.fragment_news_list.*

private const val TAG ="NewsListFragment"
//The view of MVVM architecture
class NewsListFragment : Fragment() 
   /* view binding with late init as dont want to redraw again n again
    also late init promises no nullable data when it is called later */
    private lateinit var binding: FragmentNewsListBinding
    //Kotlin property delegate used to define viewmodels
    private val viewmodel: NewsViewModel by viewModels()
    private lateinit var newsAdapter: NewsListAdapter

    override fun onCreate(savedInstanceState: Bundle?) 
        super.onCreate(savedInstanceState)
        setHasOptionsMenu(true)

    

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?,
    ): View 
        binding = FragmentNewsListBinding.inflate(layoutInflater)
        Log.i(TAG,"onCreate")

        //Creating the observer which updates the UI(Main Thread)
        viewmodel.newsMutableLiveData.observe(viewLifecycleOwner, 
            if(it!=null )
            
                hideProgressBar()
                Log.i(TAG,"Received the data")
                initAdapterModel()
                newsAdapter.setLatestData(it.rows,activity)

            
            else 
                showProgressBar()
                Toast.makeText(activity,"No data",Toast.LENGTH_LONG).show()
            

        )
        viewmodel.getDataFromApi()
        return binding.root

    

    override fun onPause() 
        super.onPause()

    

    //Binding the recycler view adapter and with the news adapter
    private fun initAdapterModel() 
        binding.recyclerView.layoutManager = LinearLayoutManager(requireContext())
        newsAdapter = NewsListAdapter()
        binding.recyclerView.adapter = newsAdapter
    
    private fun hideProgressBar() 
        progressBar.visibility = View.INVISIBLE
    

    private fun showProgressBar() 
        progressBar.visibility = View.VISIBLE
    
    override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) 
        inflater.inflate(R.menu.scrolltotop,menu)
        super.onCreateOptionsMenu(menu, inflater)

    
    override fun onOptionsItemSelected(item: MenuItem): Boolean 
        binding.recyclerView.smoothScrollToPosition(0)
        return super.onOptionsItemSelected(item)
    
    companion object 

        @JvmStatic
        fun newInstance() =
            NewsListFragment()
    

    
    
    

【问题讨论】:

【参考方案1】:

我通过使用事件和保存实例状态找到了解决方案。

【讨论】:

以上是关于使用视图模型时不保留方向更改的主要内容,如果未能解决你的问题,请参考以下文章

使用 HTML 助手时不正确的列表模型绑定索引

eplan模型视图中怎么移动文本

怎样才能只保留剖视图 删除原先画剖面线的试图?

ASP.net MVC - 如何在各种视图中保留模型

如何在 .Net Core 中提交表单而不离开当前视图并保留当前模型

solidworks工程图如何更换视图中的模型文件