标签: android-viewmodel

Android:通过Activity中的LiveData和ViewModel观察Room DB

我创建了一个基本示例,其中的活动是通过 LiveData 观察房间数据库。欲了解更多信息,请查看以下代码:

    @Dao
    interface NoteDao {
        @Query("SELECT * FROM note ORDER BY date_created DESC")
        fun getAll(): LiveData<List<Note>>
    }

    // Repository
    class ReadersRepository(private val context: Context) {
        private val appDatabase = Room.databaseBuilder(context, AppDatabase::class.java, DATABASE_NAME)
                    .build()
        fun getAllNotes(): LiveData<List<Note>> {
            return appDatabase.getNoteDao().getAll()
        }
    }

    // ViewModel   
    class AllNotesViewModel(application: Application) : AndroidViewModel(application) {
        private val repository = ReadersRepository(application)
        internal var allNotesLiveData: LiveData<List<Note>> = repository.getAllNotes()
    }

    // Activity
    class MainActivity : BaseActivity<AllNotesViewModel>() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            setSupportActionBar(toolbar)

            viewModel.allNotesLiveData.observe(this, Observer …
Run Code Online (Sandbox Code Playgroud)

android android-room android-livedata android-viewmodel

2
推荐指数
1
解决办法
2288
查看次数

nav_graph 中两个片段之间的共享视图模型

我有一个应用程序,其中有一个活动和大约 29 个片段nav_graph,其中两个片段用于身份验证,我需要使用 a 在这两个片段之间共享数据,shared view model但不与其他片段共享数据。

因此,我创建了我的并使用库的一部分ViewModel在两个片段中实例化了它。viewModels()fragment-ktx

private val viewModel: AuthViewModel by viewModels()
Run Code Online (Sandbox Code Playgroud)

但是,一旦我使用导航到第二个片段,findNavController().navigate()我就会丢失其中的所有数据AuthViewModel

AuthViewModel.kt

class AuthViewModel @ViewModelInject constructor(
    private val authRepository: AuthRepository
) : BaseViewModel()
Run Code Online (Sandbox Code Playgroud)

我这里还缺少任何其他步骤吗?

编辑

onViewCreated我正在从该方法访问数据

android android-studio android-navigation android-viewmodel android-architecture-navigation

2
推荐指数
1
解决办法
4182
查看次数

通过 viewModels 将调用 Fragment 所使用的 ViewModel 共享给 DialogFragment 使用

我有一个SearchFragment带有以下代码的。

@AndroidEntryPoint
class SearchFragment :
    Fragment(),
    View.OnClickListener {
    ...
    private var _binding: FragSearchBinding? = null
    private val binding get() = _binding as FragSearchBinding
    private val viewmodel by viewModels<SearchViewModel>()

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    )
        : View {
        _binding = FragSearchBinding.inflate(inflater, container, false)
        binding.fragSearchSearchResultFilter.setOnClickListener(this)
        return binding.root
    }

    ...

    private fun showFilterDialog() {
        val dialog = FilterBottomSheetDialogFragment.newInstance()
        dialog.show(parentFragmentManager, "filter_bsd_tag")
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

我正在展示一个FilterBottomSheetDialogFragment使用它的方法SearchFragment。我想将 ViewModel 传递SearchFragmentDialogFragment. 我的FilterBottomSheetDialogFragment. …

viewmodel android-fragments kotlin android-viewmodel android-ktx

2
推荐指数
1
解决办法
1342
查看次数

ViewModels + Hilt:无法将使用 JVM 目标 1.8 构建的字节码内联到使用 JVM 目标 1.6 构建的字节码中

我在我的 Android 应用程序 (Kotlin) 中使用视图模型和 Hilt。但我在初始化视图模型时遇到问题:

private val myViewModel: MyViewModel by viewModels()

该应用程序编译正常,我可以运行它,但 Android Studio 指示错误,当我将光标移到其上方时,我收到以下消息:

无法将使用 JVM 目标 1.8 构建的字节码内联到使用 JVM 目标 1.6 构建的字节码中。请指定正确的“-jvm-target”

在我的构建 gradle 中,我为编译选项指定了 Java 1.8(甚至对于 Kotlin)。

compileOptions {
   sourceCompatibility JavaVersion.VERSION_1_8
   targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
   jvmTarget = JavaVersion.VERSION_1_8
}
Run Code Online (Sandbox Code Playgroud)

这是我的视图模型和片段的注释

@HiltViewModel
class MyViewModel: ViewModel()
Run Code Online (Sandbox Code Playgroud)

@AndroidEntryPoint
class MyFragment: Fragment()
Run Code Online (Sandbox Code Playgroud)

我的一些依赖项:

'androidx.core:core-ktx:1.5.0'
'androidx.appcompat:appcompat:1.3.0'
'com.google.dagger:hilt-android:2.35'
'com.google.dagger:hilt-android-compiler:2.35'
"androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"
Run Code Online (Sandbox Code Playgroud)

有人遇到过类似的问题吗?感谢您的帮助 !

android gradle kotlin android-viewmodel dagger-hilt

2
推荐指数
1
解决办法
1567
查看次数

即使设置了lifecycleOwner,Android Fragment ViewModel数据绑定也不会更新UI

ViewModel我想在单击按钮时使用带有数据绑定的复选框来禁用复选框,但除非片段被销毁并重新创建,否则 UI 不会更新。

似乎有很多类似的问题,但最相似的问题似乎都可以通过设置来解决binding.lifecycleOwner,我已经完成了。

片段_复选框_数据绑定.xml:

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".CheckboxDatabindingFragment">
    
    <data>
        <variable
            name="viewModel"
            type=".CheckboxDatabindingFragmentViewModel" />
    </data>

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

        <CheckBox
            android:id="@+id/my_checkbox"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:enabled="@{viewModel.checkboxEnabled}" />

        <Button
            android:id="@+id/my_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{() -> viewModel.startClicked()}" />
    
    </LinearLayout>
</layout>
Run Code Online (Sandbox Code Playgroud)

CheckboxDatabindingFragment.kt:

class CheckboxDatabindingFragment() : Fragment() {
    private lateinit var viewModel: CheckboxDatabindingFragmentViewModel

    private var _binding: FragmentCheckboxDatabindingBinding? = null
    private val binding get() = _binding!!

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        viewModel = ViewModelProvider(this).get(CheckboxDatabindingFragmentViewModel::class.java )
        
        _binding …
Run Code Online (Sandbox Code Playgroud)

android android-fragments kotlin android-databinding android-viewmodel

2
推荐指数
1
解决办法
1132
查看次数

从第二个片段访问时 ViewModel 数据丢失状态

我用于保存用户登录数据的 ViewModel 遇到问题。

用户登录后,我使用片段 A 中的用户数据更新此 ViewModel,但是当我尝试访问片段 B 中的数据时,我刚刚设置的数据字段始终为空。

当片段 B 初始化时,userLiveData 字段最初不会被观察到,但是,当我user从片段 B 触发对对象的更改时,会在片段 B 中正确观察到更改。看来我的 ViewModel 中字段的先前值永远不会到达片段B,但是新的价值观可以。

为了进行完整性检查,我创建了一个简单的字符串变量(甚至不是 LiveData 对象),将其设置为片段 A 中的值,然后,在导航到片段 BI 后打印该值:它每次都未初始化。就好像我注入到片段 B 中的 ViewModel 与我注入到片段 A 中的 ViewModel 完全分开。

我缺少什么导致片段 B 中的 ViewModel 观察最初不使用user片段 A 中设置的最后一个已知值触发?

片段A

class FragmentA : Fragment() {
    private val viewModel: LoginViewModel by viewModel()

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

        viewModel.user.observe(this, {
            it?.let {
                //Called successfully every time
                navigateToFragmentB()
            }
        })
        
        val mockUserData = User() …
Run Code Online (Sandbox Code Playgroud)

android mvvm android-fragments android-livedata android-viewmodel

2
推荐指数
1
解决办法
973
查看次数

使用 Factory 创建共享 ViewModel

我有一个带有 3 个选项卡的 TabLayout 的 DocumentsFragment:

TabRulesFragment、TabProceduresFragment、TabGuidanceFragment

在 DocumentsFragment 中,我使用工厂初始化共享 viewModel DocumentsSharedViewModel:

class DocumentsFragment : Fragment() {

    private lateinit var sharedViewModel: DocumentsSharedViewModel
    private lateinit var viewPager2: ViewPager2
    private lateinit var documentsCollectionAdapter: DocumentsCollectionAdapter

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {

        val program = DocumentsFragmentArgs.fromBundle(requireArguments()).program
        val name = DocumentsFragmentArgs.fromBundle(requireArguments()).name

        val viewModelFactory = DocumentsSharedViewModelFactory(program, name)
        sharedViewModel = ViewModelProvider(this, viewModelFactory)[DocumentsSharedViewModel::class.java]
Run Code Online (Sandbox Code Playgroud)

在文档片段和 3 个选项卡片段之间共享数据。当我尝试连接到选项卡片段之一(例如 TabRulesFragment)中的共享 viewModel 时:

class TabRulesFragment : Fragment() {

    private lateinit var tabRulesRecyclerView: RecyclerView

    override fun onCreateView( …
Run Code Online (Sandbox Code Playgroud)

android android-viewmodel

2
推荐指数
1
解决办法
3266
查看次数

在 MVVM 中处理 ViewModel 和 Fragment 中的数据

我看过很多教程,但并没有真正让自己正确理解如何处理 MVVM 中的某些情况。

假设有一个从DAO使用的a 获取数据的存储库Room

class Repository(){

  fun getItems() = itemsDAO.getItems()

}
Run Code Online (Sandbox Code Playgroud)

查询 Repository 的 ViewModel

class FragmentViewModel:ViewModel(){

    val items = repository.getItems()

    fun updateItem(Item item){
       repository.updateImte(itemm)
    }
}
Run Code Online (Sandbox Code Playgroud)

还有一个片段

class MyFragment:Fragment(){

   //onViewCreated
   viewModel.items.observe(...){
        //if result, update the views
     }

  buttonUpdateItem.setOnClickListener{
    viewModel.updateItem(Item item)    
  }

}
Run Code Online (Sandbox Code Playgroud)

这是我从教程中理解的方法。基本上我有一些事情需要澄清,我想寻求你的帮助。

一种。鉴于ViewModel如果用户旋转设备并重新创建片段的这种实现,这是否意味着observe将在添加时再次查询数据库?我正在考虑 ViewModel 的更新版本,例如

  class FragmentViewModel:ViewModel(){
        private final var itemsObservable;


       init {
           itemsObservable = repository.getItems()
        }

       fun items(){
           return itemsObservable
       }

        fun updateItem(Item item){
           repository.updateImte(item)
        }
    }
Run Code Online (Sandbox Code Playgroud)

如果我是对的,这应该允许从 db …

android mvvm viewmodel android-viewmodel

1
推荐指数
1
解决办法
2382
查看次数

Android DataBinding LiveData-未通知DialogFragment和BottomSheetDialogFragment中的更改

我有这样BottomSheetDialogFragment的布局:

<data>

    <variable
        name="viewModel"
        type="com.sample.MyViewModel" />
</data>

<TextView android:id="@+id/tvValue"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text='@{String.format("%.1f", viewModel.weight)}'/>

<Button android:id="@+id/cmdUpdate"
                android:layout_height="wrap_content"
                android:layout_width="match_parent"
                android:onClick="@{() -> viewModel.updateWeight()}"
                android:text="@string/update" />
Run Code Online (Sandbox Code Playgroud)

这是kotlin代码:

  // MyViewModel
  val weight = MutableLiveData<Double>()
  fun updateWeight() {
     weight.value?.let {
        weight.value = (it + 0.1)
    }
  }

 // BottomSheetDialogFragment bind view model
 val myViewModel = ViewModelProviders.of(it, factory).get(MyViewModel::class)
 binding.viewModel = myViewModel

// code showing BottomSheet:
 val fragment = MyBottomSheetFragment()
 fragment.show(fragmentManager, "bottomsheet")
Run Code Online (Sandbox Code Playgroud)

第一次打开底片片段,它可以显示重量值,但是当我单击按钮更新重量时,什么也没有发生。从调试器中,我可以看到该updateWeight方法已调用,并且权重值已更改,但未TextView更新。这也发生在其他DialogFragment上。
如果我使用常规代码,则相同的代码也可以工作Fragment
。DialogFragment和DataBinding是否有问题?

android kotlin android-databinding android-livedata android-viewmodel

1
推荐指数
1
解决办法
546
查看次数

MutableLiveData &lt;Pair &lt;Float,Float &gt;&gt;()-&gt; Val无法重新分配

在我的Android项目中的ViewModel中:

import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData

class MainViewModel(application: Application) : AndroidViewModel(application) {
    private var waitressCallContainerHeights = MutableLiveData<Pair<Int, Int>>()

    fun init() {
           waitressCallContainerHeights.value.first = 200
    }
}
Run Code Online (Sandbox Code Playgroud)

但是我在这行得到编译错误:

       waitressCallContainerHeights.value.first = 200

Val cannot be reassigned
Run Code Online (Sandbox Code Playgroud)

我想有趣地设置第一个第二个init

android kotlin android-viewmodel

1
推荐指数
1
解决办法
67
查看次数