Android:为什么 Transformation.map 运行 尝试分配给变量?
Android: Why doesn't this Transformation.map run when trying to assign to a variable?
我正在尝试在我的项目中使用 Firebase API,但是视图模型中的变量 authenticationState
的 Transformations.map
没有 运行。我一直在关注 Google 的教程 here(link 转到该项目的 ViewModel)。
我希望稍后能够将 Transformations.map
代码添加到 FirebaseUserLiveData
文件中,但我似乎无法弄清楚为什么它不能 运行.
FirebaseUserLiveData
class FirebaseUserLiveData: LiveData<FirebaseUser?>() {
private val firebaseAuth = FirebaseAuth.getInstance()
private val authStateListener = FirebaseAuth.AuthStateListener { firebaseAuth ->
value = firebaseAuth.currentUser
}
override fun onActive() {
firebaseAuth.addAuthStateListener { authStateListener }
}
override fun onInactive() {
firebaseAuth.removeAuthStateListener(authStateListener)
}
}
SearchMovieFragmentViewModel
class SearchMovieFragmentViewModel : ViewModel() {
enum class AuthenticationState {
AUTHENTICATED, UNAUTHENTICATED, INVALID_AUTHENTICATION
}
var authenticationState = Transformations.map(FirebaseUserLiveData()) { user ->
Log.d("TEST", "in the state function")
if (user != null) {
AuthenticationState.AUTHENTICATED
} else {
AuthenticationState.UNAUTHENTICATED
}
}
SearchMovieFragment
class SearchMovieFragment : Fragment(), MovieSearchItemViewModel {
companion object {
fun newInstance() = SearchMovieFragment()
}
private lateinit var searchMovieFragmentViewModel: SearchMovieFragmentViewModel
private lateinit var binding: SearchMovieFragmentBinding
private lateinit var movieRecyclerView: RecyclerView
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
binding = DataBindingUtil.inflate(inflater, R.layout.search_movie_fragment, container, false)
searchMovieFragmentViewModel = ViewModelProvider(this).get(SearchMovieFragmentViewModel::class.java)
binding.lifecycleOwner = this
binding.viewmodel = searchMovieFragmentViewModel
binding.signOutButton.setOnClickListener {
AuthUI.getInstance().signOut(requireContext())
}
searchMovieFragmentViewModel.authenticationState.observe(viewLifecycleOwner, Observer { state ->
when (state) {
AUTHENTICATED -> searchMovieFragmentViewModel.signedIn = View.VISIBLE
UNAUTHENTICATED -> searchMovieFragmentViewModel.signedIn = View.GONE
}
})
return binding.root
}
}
那是因为一旦您开始像 Transformations.map(FirebaseUserLiveData()) { user ->
一样观察它,您就没有保留 FirebaseUserLiveData()
的引用。
您必须具有要映射或传输到另一种形式的 Livedata.
的 Livedata 的引用
它就像一个观察链,链中的所有LiveData都应该被观察或者应该有某种观察者在下面行,主要use-case是将某种形式的实时数据转换成你想要的东西,例如:
class YourRepository{ // your repo, that connected to a network that keeps up to date some data
val IntegerResource: LiveData<Int> = SomeRetrofitInstance.fetchFromNetwork() //updating some resource from network
}
class YourViewModel{
val repository = YourRepository()
//this will start observe the repository livedata and map it to string resource
var StringResource: Livedata<String> = Transformations.map( repository.IntegerResource ) { integerValue ->
integerValue.toString()
}
我的观点是,您必须让正在转换的 LiveData 保持活动状态。希望有所帮助。
应该是.addAuthStateListener(authStateListener)
而不是{ authStateListener }
我正在尝试在我的项目中使用 Firebase API,但是视图模型中的变量 authenticationState
的 Transformations.map
没有 运行。我一直在关注 Google 的教程 here(link 转到该项目的 ViewModel)。
我希望稍后能够将 Transformations.map
代码添加到 FirebaseUserLiveData
文件中,但我似乎无法弄清楚为什么它不能 运行.
FirebaseUserLiveData
class FirebaseUserLiveData: LiveData<FirebaseUser?>() {
private val firebaseAuth = FirebaseAuth.getInstance()
private val authStateListener = FirebaseAuth.AuthStateListener { firebaseAuth ->
value = firebaseAuth.currentUser
}
override fun onActive() {
firebaseAuth.addAuthStateListener { authStateListener }
}
override fun onInactive() {
firebaseAuth.removeAuthStateListener(authStateListener)
}
}
SearchMovieFragmentViewModel
class SearchMovieFragmentViewModel : ViewModel() {
enum class AuthenticationState {
AUTHENTICATED, UNAUTHENTICATED, INVALID_AUTHENTICATION
}
var authenticationState = Transformations.map(FirebaseUserLiveData()) { user ->
Log.d("TEST", "in the state function")
if (user != null) {
AuthenticationState.AUTHENTICATED
} else {
AuthenticationState.UNAUTHENTICATED
}
}
SearchMovieFragment
class SearchMovieFragment : Fragment(), MovieSearchItemViewModel {
companion object {
fun newInstance() = SearchMovieFragment()
}
private lateinit var searchMovieFragmentViewModel: SearchMovieFragmentViewModel
private lateinit var binding: SearchMovieFragmentBinding
private lateinit var movieRecyclerView: RecyclerView
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
binding = DataBindingUtil.inflate(inflater, R.layout.search_movie_fragment, container, false)
searchMovieFragmentViewModel = ViewModelProvider(this).get(SearchMovieFragmentViewModel::class.java)
binding.lifecycleOwner = this
binding.viewmodel = searchMovieFragmentViewModel
binding.signOutButton.setOnClickListener {
AuthUI.getInstance().signOut(requireContext())
}
searchMovieFragmentViewModel.authenticationState.observe(viewLifecycleOwner, Observer { state ->
when (state) {
AUTHENTICATED -> searchMovieFragmentViewModel.signedIn = View.VISIBLE
UNAUTHENTICATED -> searchMovieFragmentViewModel.signedIn = View.GONE
}
})
return binding.root
}
}
那是因为一旦您开始像 Transformations.map(FirebaseUserLiveData()) { user ->
一样观察它,您就没有保留 FirebaseUserLiveData()
的引用。
您必须具有要映射或传输到另一种形式的 Livedata.
它就像一个观察链,链中的所有LiveData都应该被观察或者应该有某种观察者在下面行,主要use-case是将某种形式的实时数据转换成你想要的东西,例如:
class YourRepository{ // your repo, that connected to a network that keeps up to date some data
val IntegerResource: LiveData<Int> = SomeRetrofitInstance.fetchFromNetwork() //updating some resource from network
}
class YourViewModel{
val repository = YourRepository()
//this will start observe the repository livedata and map it to string resource
var StringResource: Livedata<String> = Transformations.map( repository.IntegerResource ) { integerValue ->
integerValue.toString()
}
我的观点是,您必须让正在转换的 LiveData 保持活动状态。希望有所帮助。
应该是.addAuthStateListener(authStateListener)
而不是{ authStateListener }