Skip to content
This repository was archived by the owner on Dec 16, 2023. It is now read-only.

Commit 542b6b7

Browse files
committed
Use coroutines instead of listeners for Firebase Auth
1 parent d48a8de commit 542b6b7

10 files changed

Lines changed: 129 additions & 91 deletions

File tree

app/src/main/java/com/marknkamau/justjava/ui/login/LogInActivity.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import com.marknkamau.justjava.data.local.PreferencesRepository
1414
import com.marknkamau.justjava.ui.signup.SignUpActivity
1515
import com.marknkamau.justjava.utils.trimmedText
1616
import kotlinx.android.synthetic.main.activity_log_in.*
17+
import kotlinx.coroutines.Dispatchers
1718
import org.koin.android.ext.android.inject
1819

1920
class LogInActivity : AppCompatActivity(), LogInView, View.OnClickListener {
@@ -28,7 +29,7 @@ class LogInActivity : AppCompatActivity(), LogInView, View.OnClickListener {
2829
super.onCreate(savedInstanceState)
2930
setContentView(R.layout.activity_log_in)
3031

31-
presenter = LogInPresenter(this, preferencesRepository, authService, databaseService)
32+
presenter = LogInPresenter(this, preferencesRepository, authService, databaseService, Dispatchers.Main)
3233
presenter.checkSignInStatus()
3334

3435
btnLogin.setOnClickListener(this)
@@ -41,6 +42,11 @@ class LogInActivity : AppCompatActivity(), LogInView, View.OnClickListener {
4142
presenter.checkSignInStatus()
4243
}
4344

45+
override fun onStop() {
46+
super.onStop()
47+
presenter.cancel()
48+
}
49+
4450
override fun onClick(view: View) {
4551
when (view) {
4652
btnLogin -> signIn()

app/src/main/java/com/marknkamau/justjava/ui/login/LogInPresenter.kt

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,24 @@ import com.marknjunge.core.model.UserDetails
55
import com.marknjunge.core.auth.AuthService
66
import com.marknjunge.core.data.firebase.ClientDatabaseService
77
import com.marknjunge.core.data.firebase.WriteListener
8+
import kotlinx.coroutines.CoroutineDispatcher
9+
import kotlinx.coroutines.CoroutineScope
10+
import kotlinx.coroutines.Job
11+
import kotlinx.coroutines.launch
812
import timber.log.Timber
913

1014
internal class LogInPresenter(private val activityView: LogInView,
1115
private val preferences: PreferencesRepository,
1216
private val auth: AuthService,
13-
private val database: ClientDatabaseService) {
17+
private val database: ClientDatabaseService,
18+
mainDispatcher: CoroutineDispatcher) {
19+
20+
private val job = Job()
21+
private val uiScope = CoroutineScope(job + mainDispatcher)
22+
23+
fun cancel() {
24+
job.cancel()
25+
}
1426

1527
fun checkSignInStatus() {
1628
if (auth.isSignedIn()) {
@@ -20,16 +32,16 @@ internal class LogInPresenter(private val activityView: LogInView,
2032

2133
fun signIn(email: String, password: String) {
2234
activityView.showDialog()
23-
auth.signIn(email, password, object : AuthService.AuthActionListener {
24-
override fun actionSuccessful(response: String) {
25-
getUserDefaults(response)
35+
uiScope.launch {
36+
try {
37+
val uid = auth.signIn(email, password)
38+
getUserDefaults(uid)
2639
setFcmToken()
40+
} catch (e: Exception) {
41+
Timber.e(e)
42+
activityView.displayMessage(e.message)
2743
}
28-
29-
override fun actionFailed(response: String) {
30-
activityView.displayMessage(response)
31-
}
32-
})
44+
}
3345
}
3446

3547
private fun getUserDefaults(id: String) {
@@ -61,14 +73,14 @@ internal class LogInPresenter(private val activityView: LogInView,
6173

6274

6375
fun resetUserPassword(email: String) {
64-
auth.sendPasswordResetEmail(email, object : AuthService.AuthActionListener {
65-
override fun actionSuccessful(response: String) {
66-
activityView.displayMessage(response)
67-
}
68-
69-
override fun actionFailed(response: String) {
70-
activityView.displayMessage(response)
76+
uiScope.launch {
77+
try {
78+
auth.sendPasswordResetEmail(email)
79+
activityView.displayMessage("Password reset email sent")
80+
} catch (e: Exception) {
81+
Timber.e(e)
82+
activityView.displayMessage(e.message)
7183
}
72-
})
84+
}
7385
}
7486
}

app/src/main/java/com/marknkamau/justjava/ui/profile/ProfileActivity.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import com.marknkamau.justjava.ui.previousOrder.PreviousOrderActivity
2020

2121
import com.marknkamau.justjava.utils.trimmedText
2222
import kotlinx.android.synthetic.main.activity_profile.*
23+
import kotlinx.coroutines.Dispatchers
2324
import org.koin.android.ext.android.inject
2425

2526
class ProfileActivity : BaseActivity(), ProfileView {
@@ -45,7 +46,7 @@ class ProfileActivity : BaseActivity(), ProfileView {
4546
rvPreviousOrders.addItemDecoration(androidx.recyclerview.widget.DividerItemDecoration(this, LinearLayout.VERTICAL))
4647
rvPreviousOrders.adapter = adapter
4748

48-
presenter = ProfilePresenter(this, preferencesRepository, authService, databaseService)
49+
presenter = ProfilePresenter(this, preferencesRepository, authService, databaseService, Dispatchers.Main)
4950

5051
btnUpdateProfile.setOnClickListener { saveChanges() }
5152
}

app/src/main/java/com/marknkamau/justjava/ui/profile/ProfilePresenter.kt

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,20 @@ import com.marknjunge.core.data.firebase.WriteListener
66
import com.marknkamau.justjava.data.local.PreferencesRepository
77
import com.marknjunge.core.model.Order
88
import com.marknjunge.core.model.UserDetails
9+
import kotlinx.coroutines.CoroutineDispatcher
10+
import kotlinx.coroutines.CoroutineScope
11+
import kotlinx.coroutines.Job
12+
import kotlinx.coroutines.launch
913
import timber.log.Timber
1014

1115
internal class ProfilePresenter(private val view: ProfileView,
1216
private val preferencesRepository: PreferencesRepository,
1317
private val authenticationService: AuthService,
14-
private val databaseService: ClientDatabaseService) {
18+
private val databaseService: ClientDatabaseService,
19+
mainDispatcher: CoroutineDispatcher) {
20+
21+
private val job = Job()
22+
private val uiScope = CoroutineScope(job + mainDispatcher)
1523

1624
init {
1725
getUserDetails()
@@ -47,8 +55,9 @@ internal class ProfilePresenter(private val view: ProfileView,
4755

4856
fun updateUserDetails(name: String, phone: String, address: String) {
4957
view.showProfileProgressBar()
50-
authenticationService.setUserDisplayName(name, object : AuthService.AuthActionListener {
51-
override fun actionSuccessful(response: String) {
58+
uiScope.launch {
59+
try {
60+
authenticationService.setUserDisplayName(name)
5261
databaseService.updateUserDetails(userDetails.id, name, phone, address, object : WriteListener {
5362
override fun onSuccess() {
5463
val newUserDetails = UserDetails(userDetails.id, userDetails.email, name, phone, address)
@@ -64,12 +73,12 @@ internal class ProfilePresenter(private val view: ProfileView,
6473
view.displayMessage(reason)
6574
}
6675
})
76+
} catch (e: Exception) {
77+
Timber.e(e)
78+
view.hideProfileProgressBar()
79+
view.displayMessage(e.message)
6780
}
68-
69-
override fun actionFailed(response: String) {
70-
view.displayMessage(response)
71-
}
72-
})
81+
}
7382
}
7483

7584
}

app/src/main/java/com/marknkamau/justjava/ui/signup/SignUpActivity.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import com.marknkamau.justjava.R
1212
import com.marknkamau.justjava.data.local.PreferencesRepository
1313
import com.marknkamau.justjava.utils.trimmedText
1414
import kotlinx.android.synthetic.main.activity_sign_up.*
15+
import kotlinx.coroutines.Dispatchers
1516
import org.koin.android.ext.android.inject
1617
import java.util.regex.Pattern
1718

@@ -31,7 +32,7 @@ class SignUpActivity : AppCompatActivity(), SignUpView, View.OnClickListener {
3132
super.onCreate(savedInstanceState)
3233
setContentView(R.layout.activity_sign_up)
3334

34-
presenter = SignUpPresenter(this, preferencesRepository, authService, databaseService)
35+
presenter = SignUpPresenter(this, preferencesRepository, authService, databaseService, Dispatchers.Main)
3536

3637
btnSignup.setOnClickListener(this)
3738
tvLogin.setOnClickListener(this)

app/src/main/java/com/marknkamau/justjava/ui/signup/SignUpPresenter.kt

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,44 +5,53 @@ import com.marknjunge.core.data.firebase.ClientDatabaseService
55
import com.marknjunge.core.data.firebase.WriteListener
66
import com.marknkamau.justjava.data.local.PreferencesRepository
77
import com.marknjunge.core.model.UserDetails
8+
import kotlinx.coroutines.CoroutineDispatcher
9+
import kotlinx.coroutines.CoroutineScope
10+
import kotlinx.coroutines.Job
11+
import kotlinx.coroutines.launch
812
import timber.log.Timber
913

1014
internal class SignUpPresenter(private val activityView: SignUpView,
1115
private val preferences: PreferencesRepository,
1216
private val auth: AuthService,
13-
private val database: ClientDatabaseService) {
17+
private val database: ClientDatabaseService,
18+
mainDispatcher: CoroutineDispatcher) {
19+
20+
private val job = Job()
21+
private val uiScope = CoroutineScope(job + mainDispatcher)
1422

1523
fun createUser(email: String, password: String, name: String, phone: String, address: String) {
1624
activityView.disableUserInteraction()
1725

18-
auth.createUser(email, password, object : AuthService.AuthActionListener {
19-
override fun actionSuccessful(response: String) {
26+
uiScope.launch {
27+
try {
28+
auth.createUser(email, password)
2029
signInUser(email, password, name, phone, address)
21-
}
22-
23-
override fun actionFailed(response: String) {
30+
} catch (e: Exception) {
31+
Timber.e(e)
2432
activityView.enableUserInteraction()
25-
activityView.displayMessage(response)
33+
activityView.displayMessage(e.message ?: "Unable to sign up")
2634
}
27-
})
35+
}
2836
}
2937

3038
private fun signInUser(email: String, password: String, name: String, phone: String, address: String) {
31-
auth.signIn(email, password, object : AuthService.AuthActionListener {
32-
override fun actionSuccessful(response: String) {
33-
setUserDisplayName(response, email, name, phone, address)
34-
}
35-
36-
override fun actionFailed(response: String) {
39+
uiScope.launch {
40+
try {
41+
val uid = auth.signIn(email, password)
42+
setUserDisplayName(uid, email, name, phone, address)
43+
} catch (e: Exception) {
44+
Timber.e(e)
3745
activityView.enableUserInteraction()
38-
activityView.displayMessage(response)
46+
activityView.displayMessage(e.message ?: "Unable to sign in")
3947
}
40-
})
48+
}
4149
}
4250

43-
private fun setUserDisplayName(id:String, email: String, name: String, phone: String, address: String) {
44-
auth.setUserDisplayName(name, object : AuthService.AuthActionListener {
45-
override fun actionSuccessful(response: String) {
51+
private fun setUserDisplayName(id: String, email: String, name: String, phone: String, address: String) {
52+
uiScope.launch {
53+
try {
54+
auth.setUserDisplayName(name)
4655
val userDetails = UserDetails(id, email, name, phone, address)
4756

4857
database.saveUserDetails(userDetails, object : WriteListener {
@@ -59,17 +68,15 @@ internal class SignUpPresenter(private val activityView: SignUpView,
5968
activityView.displayMessage(reason)
6069
}
6170
})
62-
63-
}
64-
65-
override fun actionFailed(response: String) {
71+
} catch (e: Exception) {
72+
Timber.e(e)
6673
activityView.enableUserInteraction()
67-
activityView.displayMessage(response)
74+
activityView.displayMessage(e.message ?: "Unable to create account")
6875
}
69-
})
76+
}
7077
}
7178

72-
private fun setFcmToken(){
79+
private fun setFcmToken() {
7380
database.updateUserFcmToken(auth.getCurrentUser().userId, object : WriteListener {
7481
override fun onError(reason: String) {
7582
Timber.e(reason)

core/src/main/java/com/marknjunge/core/auth/AuthService.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ import com.marknjunge.core.model.AuthUser
66
interface AuthService {
77
fun addStateListener(listener: FirebaseAuth.AuthStateListener)
88

9-
fun createUser(email: String, password: String, listener: AuthActionListener)
9+
suspend fun createUser(email: String, password: String)
1010

11-
fun signIn(email: String, password: String, listener: AuthActionListener)
11+
suspend fun signIn(email: String, password: String): String
1212

13-
fun sendPasswordResetEmail(email: String, listener: AuthActionListener)
13+
suspend fun sendPasswordResetEmail(email: String)
1414

15-
fun setUserDisplayName(name: String, listener: AuthActionListener)
15+
suspend fun setUserDisplayName(name: String)
1616

1717
fun getCurrentUser(): AuthUser
1818

core/src/main/java/com/marknjunge/core/auth/AuthServiceImpl.kt

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.marknjunge.core.auth
33
import com.google.firebase.auth.FirebaseAuth
44
import com.google.firebase.auth.UserProfileChangeRequest
55
import com.marknjunge.core.model.AuthUser
6+
import kotlinx.coroutines.tasks.await
67

78
internal class AuthServiceImpl : AuthService {
89
private val firebaseAuth: FirebaseAuth by lazy { FirebaseAuth.getInstance() }
@@ -11,38 +12,21 @@ internal class AuthServiceImpl : AuthService {
1112
firebaseAuth.addAuthStateListener(listener)
1213
}
1314

14-
override fun createUser(email: String, password: String, listener: AuthService.AuthActionListener) {
15-
firebaseAuth.createUserWithEmailAndPassword(email, password)
16-
.addOnSuccessListener { listener.actionSuccessful("Account created") }
17-
.addOnFailureListener { exception ->
18-
listener.actionFailed(exception.message ?: "Unable to create account")
19-
}
15+
override suspend fun createUser(email: String, password: String) {
16+
firebaseAuth.createUserWithEmailAndPassword(email, password).await()
2017
}
2118

22-
override fun signIn(email: String, password: String, listener: AuthService.AuthActionListener) {
23-
firebaseAuth.signInWithEmailAndPassword(email, password)
24-
.addOnSuccessListener { listener.actionSuccessful(it.user.uid) }
25-
.addOnFailureListener { exception ->
26-
listener.actionFailed(exception.message ?: "Unable to sign in")
27-
}
19+
override suspend fun signIn(email: String, password: String): String {
20+
return firebaseAuth.signInWithEmailAndPassword(email, password).await().user.uid
2821
}
2922

30-
override fun sendPasswordResetEmail(email: String, listener: AuthService.AuthActionListener) {
31-
firebaseAuth.sendPasswordResetEmail(email)
32-
.addOnSuccessListener { listener.actionSuccessful("Password reset email sent") }
33-
.addOnFailureListener { exception ->
34-
listener.actionFailed(exception.message ?: "Unable to send email")
35-
}
23+
override suspend fun sendPasswordResetEmail(email: String) {
24+
firebaseAuth.sendPasswordResetEmail(email).await()
3625
}
3726

38-
override fun setUserDisplayName(name: String, listener: AuthService.AuthActionListener) {
27+
override suspend fun setUserDisplayName(name: String) {
3928
val profileUpdate = UserProfileChangeRequest.Builder().setDisplayName(name).build()
40-
41-
firebaseAuth.currentUser?.updateProfile(profileUpdate)
42-
?.addOnSuccessListener { listener.actionSuccessful("User's name set") }
43-
?.addOnFailureListener { exception ->
44-
listener.actionFailed(exception.message ?: "Unable to update name")
45-
}
29+
firebaseAuth.currentUser?.updateProfile(profileUpdate)?.await()
4630
}
4731

4832
override fun getCurrentUser(): AuthUser {

justjavastaff/src/main/java/com/marknkamau/justjavastaff/ui/login/LogInActivity.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import com.marknkamau.justjavastaff.R
1313
import com.marknkamau.justjavastaff.ui.main.MainActivity
1414

1515
import kotlinx.android.synthetic.main.activity_log_in.*
16+
import kotlinx.coroutines.Dispatchers
1617

1718
class LogInActivity : AppCompatActivity(), LoginView, View.OnClickListener {
1819

@@ -31,12 +32,17 @@ class LogInActivity : AppCompatActivity(), LoginView, View.OnClickListener {
3132
finish()
3233
}
3334

34-
presenter = LoginPresenter(auth, this)
35+
presenter = LoginPresenter(auth, this, Dispatchers.Main)
3536

3637
btnLogIn.setOnClickListener(this)
3738
imgVisibility.setOnClickListener(this)
3839
}
3940

41+
override fun onStop() {
42+
super.onStop()
43+
presenter.cancel()
44+
}
45+
4046
override fun onClick(view: View) {
4147
when (view.id) {
4248
R.id.imgVisibility -> if (passVisible) {

0 commit comments

Comments
 (0)