Android 使用MVVM和数据绑定更改每个片段中的工具栏标题
我希望在我的片段页面中更改主活动中的工具栏标题。我的项目基于MVVM体系结构,带有数据绑定 这是我的主要活动。xmlAndroid 使用MVVM和数据绑定更改每个片段中的工具栏标题,android,kotlin,android-toolbar,android-databinding,android-mvvm,Android,Kotlin,Android Toolbar,Android Databinding,Android Mvvm,我希望在我的片段页面中更改主活动中的工具栏标题。我的项目基于MVVM体系结构,带有数据绑定 这是我的主要活动。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
<?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"
xmlns:tools="http://schemas.android.com/tools">
<data>
<variable
name="viewModel"
type="com.lalsoft.toolbar_mvvm_databinding.viewmodel.MainViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".view.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="0dp"
android:theme="@style/AppTheme.AppBarOverlay">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:minHeight="?attr/actionBarSize"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:titleTextColor="@android:color/white"
app:navigationIcon="@drawable/ic_arrow_back"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay"
app:navigationOnClickListener="@{()->viewModel.navBackClicked()}"
app:title="@{viewModel.toolbarTitle}"/>
</com.google.android.material.appbar.AppBarLayout>
<FrameLayout
android:id="@+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
我也在为同样的问题挣扎!
我认为问题在于生命周期所有者。但是找不到答案。
目前,我观察ViewModel中的值,并在观察者内部指定值。
但我认为还有更好的办法 我和同样的人斗争!
我认为问题在于生命周期所有者。但是找不到答案。
目前,我观察ViewModel中的值,并在观察者内部指定值。
但我认为还有更好的办法 如果片段使用的是ViewModel,则应将其作用域限定为主机活动,请由activityViewModels()委托使用:
@AndroidEntryPoint
class HomeFragment : Fragment() {
private val viewModel: SharedViewModel by activityViewModels()
}
我认为这个答案也会有所帮助
当您使用by viewModels时,您正在创建一个作用域为该单个片段的ViewModel—这意味着每个片段都有其自己的ViewModel类实例。如果希望单个ViewModel实例的作用域为整个活动,则希望按activityViewModels使用如果片段正在使用ViewModel,则应将其作用域为主机活动,则按activityViewModels()委托使用:
@AndroidEntryPoint
class HomeFragment : Fragment() {
private val viewModel: SharedViewModel by activityViewModels()
}
我认为这个答案也会有所帮助
当您使用by viewModels时,您正在创建一个作用域为该单个片段的ViewModel—这意味着每个片段都有其自己的ViewModel类实例。如果希望单个ViewModel实例的作用域为整个活动,则希望由activityViewModels使用
private const val TAG = "FirstViewModel"
class FirstViewModel : MainViewModel() {
private val _navigateToDetails = MutableLiveData<Event<String>>()
val navigateToFragment: LiveData<Event<String>>
get() = _navigateToDetails
init {
Log.e(TAG, "Inside Init")
toolbarTitle.value="First Fragment"
}
fun onBtnClick() {
_navigateToDetails.value = Event("Second Fragment")
}
}
private const val TAG = "FirstFragment"
class FirstFragment : Fragment() {
private lateinit var viewModel: FirstViewModel
private lateinit var dataBinding: FirstFragmentBinding
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
dataBinding = DataBindingUtil.inflate(inflater, R.layout.first_fragment, container, false)
return dataBinding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
viewModel = ViewModelProvider(this).get(FirstViewModel::class.java)
viewModel.toolbarTitle.observe(viewLifecycleOwner, toolbarTitleObserver)
viewModel.navigateToFragment.observe(viewLifecycleOwner, navigateToFragmentObserver)
//(activity as MainActivity?)!!.toolbar.title = "Check"
dataBinding.viewModel = viewModel
}
private val toolbarTitleObserver = Observer<String> {
Log.e(TAG, "Title set : $it")
//(activity as MainActivity?)!!.toolbar.title = "Check"
//Log.e(TAG, "Title set : Check")
}
private val navigateToFragmentObserver = Observer<Event<String>> { it ->
it.getContentIfNotHandled()?.let { // Only proceed if the event has never been handled
Log.i(TAG, "checkIt string $it")
parentFragmentManager.beginTransaction().replace(
R.id.fragment_container,
SecondFragment()
).addToBackStack(null).commit()
}
}
}
@AndroidEntryPoint
class HomeFragment : Fragment() {
private val viewModel: SharedViewModel by activityViewModels()
}