Skip to content

Commit bc9912a

Browse files
committed
refactor(firebaseui): move Firebase calls to ViewModel
1 parent 8fffb30 commit bc9912a

File tree

2 files changed

+89
-46
lines changed

2 files changed

+89
-46
lines changed

auth/app/src/main/java/com/google/firebase/quickstart/auth/kotlin/FirebaseUIFragment.kt

+28-46
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,20 @@ import android.os.Bundle
55
import android.view.LayoutInflater
66
import android.view.View
77
import android.view.ViewGroup
8-
import android.widget.Toast
8+
import androidx.core.view.isGone
99
import androidx.fragment.app.Fragment
10+
import androidx.fragment.app.viewModels
11+
import androidx.lifecycle.Lifecycle
12+
import androidx.lifecycle.lifecycleScope
13+
import androidx.lifecycle.repeatOnLifecycle
1014
import com.firebase.ui.auth.AuthUI
1115
import com.firebase.ui.auth.FirebaseAuthUIActivityResultContract
1216
import com.firebase.ui.auth.data.model.FirebaseAuthUIAuthenticationResult
13-
import com.google.firebase.auth.FirebaseAuth
14-
import com.google.firebase.auth.FirebaseUser
15-
import com.google.firebase.auth.ktx.auth
16-
import com.google.firebase.ktx.Firebase
17+
import com.google.android.material.snackbar.Snackbar
1718
import com.google.firebase.quickstart.auth.BuildConfig
1819
import com.google.firebase.quickstart.auth.R
1920
import com.google.firebase.quickstart.auth.databinding.FragmentFirebaseUiBinding
21+
import kotlinx.coroutines.launch
2022

2123
/**
2224
* Demonstrate authentication using the FirebaseUI-Android library. This fragment demonstrates
@@ -26,7 +28,7 @@ import com.google.firebase.quickstart.auth.databinding.FragmentFirebaseUiBinding
2628
*/
2729
class FirebaseUIFragment : Fragment() {
2830

29-
private lateinit var auth: FirebaseAuth
31+
private val viewModel by viewModels<FirebaseUIViewModel>()
3032

3133
private var _binding: FragmentFirebaseUiBinding? = null
3234
private val binding: FragmentFirebaseUiBinding
@@ -36,7 +38,7 @@ class FirebaseUIFragment : Fragment() {
3638
// possible customization see: https://github.com/firebase/firebaseui-android
3739
private val signInLauncher = registerForActivityResult(
3840
FirebaseAuthUIActivityResultContract()
39-
) { result -> this.onSignInResult(result)}
41+
) { result -> this.onSignInResult(result) }
4042

4143
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
4244
_binding = FragmentFirebaseUiBinding.inflate(inflater, container, false)
@@ -46,62 +48,42 @@ class FirebaseUIFragment : Fragment() {
4648
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
4749
super.onViewCreated(view, savedInstanceState)
4850

49-
// Initialize Firebase Auth
50-
auth = Firebase.auth
51-
5251
binding.signInButton.setOnClickListener { startSignIn() }
53-
binding.signOutButton.setOnClickListener { signOut() }
54-
}
55-
56-
override fun onStart() {
57-
super.onStart()
58-
updateUI(auth.currentUser)
52+
binding.signOutButton.setOnClickListener { viewModel.signOut() }
53+
54+
lifecycleScope.launch {
55+
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
56+
viewModel.uiState.collect { uiState ->
57+
binding.status.text = uiState.status
58+
binding.detail.text = uiState.detail
59+
60+
binding.signInButton.isGone = !uiState.isSignInVisible
61+
binding.signOutButton.isGone = uiState.isSignInVisible
62+
}
63+
}
64+
}
5965
}
6066

6167
private fun onSignInResult(result: FirebaseAuthUIAuthenticationResult) {
6268
if (result.resultCode == Activity.RESULT_OK) {
6369
// Sign in succeeded
64-
updateUI(auth.currentUser)
6570
} else {
6671
// Sign in failed
67-
Toast.makeText(context, "Sign In Failed", Toast.LENGTH_SHORT).show()
68-
updateUI(null)
72+
Snackbar.make(requireView(), "Sign In Failed", Snackbar.LENGTH_SHORT).show()
6973
}
74+
viewModel.showSignedInUser()
7075
}
7176

7277
private fun startSignIn() {
7378
val intent = AuthUI.getInstance().createSignInIntentBuilder()
74-
.setIsSmartLockEnabled(!BuildConfig.DEBUG)
75-
.setAvailableProviders(listOf(AuthUI.IdpConfig.EmailBuilder().build()))
76-
.setLogo(R.mipmap.ic_launcher)
77-
.build()
79+
.setIsSmartLockEnabled(!BuildConfig.DEBUG)
80+
.setAvailableProviders(listOf(AuthUI.IdpConfig.EmailBuilder().build()))
81+
.setLogo(R.mipmap.ic_launcher)
82+
.build()
7883

7984
signInLauncher.launch(intent)
8085
}
8186

82-
private fun updateUI(user: FirebaseUser?) {
83-
if (user != null) {
84-
// Signed in
85-
binding.status.text = getString(R.string.firebaseui_status_fmt, user.email)
86-
binding.detail.text = getString(R.string.id_fmt, user.uid)
87-
88-
binding.signInButton.visibility = View.GONE
89-
binding.signOutButton.visibility = View.VISIBLE
90-
} else {
91-
// Signed out
92-
binding.status.setText(R.string.signed_out)
93-
binding.detail.text = null
94-
95-
binding.signInButton.visibility = View.VISIBLE
96-
binding.signOutButton.visibility = View.GONE
97-
}
98-
}
99-
100-
private fun signOut() {
101-
AuthUI.getInstance().signOut(requireContext())
102-
updateUI(null)
103-
}
104-
10587
override fun onDestroyView() {
10688
super.onDestroyView()
10789
_binding = null
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package com.google.firebase.quickstart.auth.kotlin
2+
3+
import androidx.lifecycle.ViewModel
4+
import com.google.firebase.auth.FirebaseAuth
5+
import com.google.firebase.auth.FirebaseUser
6+
import com.google.firebase.auth.ktx.auth
7+
import com.google.firebase.ktx.Firebase
8+
import kotlinx.coroutines.flow.MutableStateFlow
9+
import kotlinx.coroutines.flow.StateFlow
10+
import kotlinx.coroutines.flow.update
11+
12+
class FirebaseUIViewModel(
13+
private val firebaseAuth: FirebaseAuth = Firebase.auth
14+
) : ViewModel() {
15+
private val _uiState = MutableStateFlow(UiState())
16+
val uiState: StateFlow<UiState> = _uiState
17+
18+
data class UiState(
19+
var status: String = "",
20+
var detail: String? = null,
21+
var isSignInVisible: Boolean = true
22+
)
23+
24+
init {
25+
// Check if user is signed in (non-null) and update UI accordingly.
26+
showSignedInUser()
27+
}
28+
29+
fun showSignedInUser() {
30+
val firebaseUser = firebaseAuth.currentUser
31+
updateUiState(firebaseUser)
32+
}
33+
34+
fun signOut() {
35+
updateUiState(null)
36+
}
37+
38+
private fun updateUiState(user: FirebaseUser?) {
39+
if (user != null) {
40+
_uiState.update { currentUiState ->
41+
currentUiState.copy(
42+
status = "Firebase User: ${user.displayName}",
43+
detail = "Firebase UID: ${user.uid}",
44+
isSignInVisible = false
45+
)
46+
}
47+
} else {
48+
_uiState.update { currentUiState ->
49+
currentUiState.copy(
50+
status = "Signed out",
51+
detail = null,
52+
isSignInVisible = true
53+
)
54+
}
55+
}
56+
}
57+
58+
companion object {
59+
const val TAG = "FirebaseUIViewModel"
60+
}
61+
}

0 commit comments

Comments
 (0)