Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/228.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 如何处理ViewModel中的配置更改_Android_Mvvm_Viewmodel_Savestate - Fatal编程技术网

Android 如何处理ViewModel中的配置更改

Android 如何处理ViewModel中的配置更改,android,mvvm,viewmodel,savestate,Android,Mvvm,Viewmodel,Savestate,我有简单的登记表。当我输入数据并更改配置时,数据丢失。我在我的项目中使用ViewModel,官方文档说ViewModel可以自动处理方向更改,但它不会发生。我该如何使用SaveState存储数据,或者我在ViewModel中犯了一个错误 片段代码 class StartFragment : Fragment() { override fun onCreateView( inflater: LayoutInflater, container: ViewGr

我有简单的登记表。当我输入数据并更改配置时,数据丢失。我在我的项目中使用ViewModel,官方文档说ViewModel可以自动处理方向更改,但它不会发生。我该如何使用SaveState存储数据,或者我在ViewModel中犯了一个错误

片段代码

class StartFragment : Fragment() {
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val binding: StartFragmentBinding = DataBindingUtil.inflate(
            inflater, R.layout.start_fragment, container, false)
        val application = requireNotNull(this.activity).application

        val dataSource = UsersDatabase.getInstance(application).usersDatabaseDao
        val vm: SavedStateHandle by viewModels()
        val viewModelFactory = StartFragmentViewModelFactory(dataSource, application)

        val startFragmentViewModel =
            ViewModelProvider(
                this, viewModelFactory).get(StartFragmentViewModel::class.java)

        binding.startFragmentViewModel = startFragmentViewModel
        binding.lifecycleOwner = this

        binding.start.setOnClickListener {
                findNavController().navigate(
                    StartFragmentDirections
                        .actionStartFragmentToWebViewFragment())
                startFragmentViewModel.doneNavigation()
            }
        return binding.root
    }
}
视图模型

class StartFragmentViewModel(
    val database: UsersDatabaseDao,
    application: Application
) : AndroidViewModel(application) {
    private var viewModelJob = Job()

    override fun onCleared() {
        super.onCleared()
        viewModelJob.cancel()
    }

    private val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)
    private var user1 = MutableLiveData<User?>()


    private val _navigateToWebView = MutableLiveData<User>()
    val navigateToWebView: LiveData<User>
        get() = _navigateToWebView

    fun doneNavigation() {
        _navigateToWebView.value = null
        uiScope.launch {
            val user = User()
            insert(user)
        }
    }

    private suspend fun insert(user: User) {
        withContext(Dispatchers.IO) {
            database.insert(user)
        }
    }
}
class StartFragmentViewModel(
val数据库:UsersDatabaseDao,
应用程序:应用程序
):AndroidViewModel(应用程序){
私有变量viewModelJob=Job()
覆盖有趣的onCleared(){
super.onCleared()
viewModelJob.cancel()
}
private val uiScope=CoroutineScope(Dispatchers.Main+viewModelJob)
private var user1=MutableLiveData()
private val_navigateToWebView=MutableLiveData()
val navigateToWebView:LiveData
get()=\u navigateToWebView
娱乐活动{
_navigateToWebView.value=null
发射{
val user=user()
插入(用户)
}
}
私有挂起乐趣插入(用户:用户){
withContext(Dispatchers.IO){
数据库.insert(用户)
}
}
}
ViewModelFactory

class StartFragmentViewModelFactory (
    private val dataSource: UsersDatabaseDao,
    private val application: Application
) : ViewModelProvider.Factory {
        @Suppress("unchecked_cast")
        override fun <T : ViewModel?> create(modelClass: Class<T>): T {
            if (modelClass.isAssignableFrom(StartFragmentViewModel::class.java)) {
                return StartFragmentViewModel(dataSource, application) as T
            }
            throw IllegalArgumentException("Unknown ViewModel class")
        }
}
类StartFragmentViewModelFactory(
私有val数据源:UsersDatabaseDao,
私有val应用程序:应用程序
):ViewModelProvider.Factory{
@抑制(“未选中的_cast”)
重写趣味创建(modelClass:Class):T{
if(modelClass.isAssignableFrom(StartFragmentViewModel::class.java)){
将StartFragmentViewModel(数据源、应用程序)返回为T
}
抛出IllegalArgumentException(“未知ViewModel类”)
}
}

start_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>

        <variable
            name="startFragmentViewModel"
            type="com.example.leadsdoittest.StartFragmentViewModel" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout

        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/margin_start"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:orientation="vertical"
            app:layout_constraintGuide_begin="16dp" />

        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/margin_end"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:orientation="vertical"
            app:layout_constraintGuide_end="16dp" />

        <androidx.constraintlayout.widget.Guideline
            android:id="@+id/margin_top"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:orientation="horizontal"
            app:layout_constraintGuide_percent="0.3" />

        <com.google.android.material.textfield.TextInputLayout
            android:id="@+id/input_name"
            style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintEnd_toEndOf="@id/margin_end"
            app:layout_constraintStart_toStartOf="@id/margin_start"
            app:layout_constraintTop_toTopOf="@id/margin_top">

            <com.google.android.material.textfield.TextInputEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="@string/name" />
        </com.google.android.material.textfield.TextInputLayout>

        <com.google.android.material.textfield.TextInputLayout
            android:id="@+id/input_phone"
            style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            app:layout_constraintEnd_toEndOf="@id/margin_end"
            app:layout_constraintStart_toStartOf="@id/margin_start"
            app:layout_constraintTop_toBottomOf="@id/input_name">

            <com.google.android.material.textfield.TextInputEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:inputType="phone"
                android:hint="@string/phone_number" />
        </com.google.android.material.textfield.TextInputLayout>

        <com.google.android.material.textfield.TextInputLayout
            android:id="@+id/input_email"
            style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginTop="16dp"
            app:layout_constraintEnd_toEndOf="@id/margin_end"
            app:layout_constraintStart_toStartOf="@id/margin_start"
            app:layout_constraintTop_toBottomOf="@id/input_phone">

            <com.google.android.material.textfield.TextInputEditText
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="@string/email" />
        </com.google.android.material.textfield.TextInputLayout>

        <com.google.android.material.button.MaterialButton
            android:id="@+id/start"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="50dp"
            android:text="@string/start"
            android:textColor="@android:color/white"
            app:layout_constraintEnd_toEndOf="@id/margin_end"
            app:layout_constraintStart_toStartOf="@id/margin_start"
            app:layout_constraintTop_toBottomOf="@+id/input_email" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

使用实例变量在旋转后恢复数据。看:

   class StartFragment  : Fragment() {

    //private lateinit var homeViewModel: HomeViewModel
    var name = ""
    var email = ""
    var phone = ""
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        val binding = FragmentHomeBinding.inflate(inflater)

        binding.etName.doOnTextChanged { text, start, before, count ->
            name = text.toString()
        }
        binding.etPhone.doOnTextChanged { text, start, before, count ->
            phone = text.toString()
        }
        binding.etEmail.doOnTextChanged { text, start, before, count ->
            email = text.toString()
        }
        binding.etName.setText(name)
        binding.etEmail.setText(email)
        binding.etPhone.setText(phone)
        return binding.root
    }
}

视图状态由框架处理,因此您不需要自己实现它。但是,保存的状态取决于每个视图上都有唯一的ID,因此请尝试向每个
textinputtext

添加ID,因此我需要onCreate()和onCreateView()?如果我同时使用这两种方法,如何初始化binding.startFragmentViewModel?因为startFragmentViewModel在onCreate中初始化?添加了屏幕截图来可视化我的意思。您使用的是多视图模型吗?您是否使用动态数据绑定?我只有一个片段的ViewModel。什么是动态?动态数据绑定,这不是一个新概念。你可能听说过。好的,告诉我一件事:ui数据在旋转后被刷新,或者视图模型数据在旋转后被刷新?它成功了!你为我节省了很多时间。非常感谢。