我创建了一个基本示例,其中的活动是通过 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) 我有一个应用程序,其中有一个活动和大约 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
我有一个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 传递SearchFragment给DialogFragment. 我的FilterBottomSheetDialogFragment. …
viewmodel android-fragments kotlin android-viewmodel android-ktx
我在我的 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)
有人遇到过类似的问题吗?感谢您的帮助 !
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
我用于保存用户登录数据的 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
我有一个带有 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) 我看过很多教程,但并没有真正让自己正确理解如何处理 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 …
我有这样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
在我的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 ×9
kotlin ×5
mvvm ×2
viewmodel ×2
android-architecture-navigation ×1
android-ktx ×1
android-room ×1
dagger-hilt ×1
gradle ×1