Skip to content
This repository was archived by the owner on Jul 2, 2025. It is now read-only.

Commit 303f5ad

Browse files
adjust the position of logout observer
1 parent 61e98d5 commit 303f5ad

File tree

8 files changed

+116
-75
lines changed

8 files changed

+116
-75
lines changed

android/canonical/app/src/main/java/com/google/samples/quickstart/canonical/LoginFragment.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import com.google.samples.quickstart.canonical.SignInViewModel.Companion.GOOGLE_
2020
class LoginFragment : Fragment() {
2121

2222
private val signInVM: SignInViewModel by activityViewModels()
23-
private val profileVM : ProfileViewModel by activityViewModels()
2423

2524
private fun signIn() {
2625
val signInIntent = signInVM.getSignInIntent()

android/canonical/app/src/main/java/com/google/samples/quickstart/canonical/MainActivity.kt

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package com.google.samples.quickstart.canonical
22

3+
import android.content.Intent
34
import androidx.appcompat.app.AppCompatActivity
45
import android.os.Bundle
56
import android.util.Log
67
import androidx.activity.viewModels
78
import androidx.constraintlayout.widget.ConstraintLayout
89
import androidx.fragment.app.FragmentTransaction
10+
import androidx.lifecycle.Observer
911
import com.google.android.material.bottomnavigation.BottomNavigationView
1012
import java.lang.Exception
1113

@@ -27,29 +29,35 @@ class MainActivity : AppCompatActivity() {
2729
when (item.itemId) {
2830

2931
R.id.bottom_navigation_item_run -> {
30-
supportFragmentManager
31-
.beginTransaction()
32-
.replace(R.id.fragment_container, RunFragment())
33-
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
34-
.commit()
32+
if (!bottomNavigation.menu.findItem(R.id.bottom_navigation_item_run).isChecked) {
33+
supportFragmentManager
34+
.beginTransaction()
35+
.replace(R.id.fragment_container, RunFragment())
36+
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
37+
.commit()
38+
}
3539
true
3640
}
3741

3842
R.id.bottom_navigation_item_map -> {
39-
supportFragmentManager
40-
.beginTransaction()
41-
.replace(R.id.fragment_container, MapsFragment())
42-
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
43-
.commit()
43+
if (!bottomNavigation.menu.findItem(R.id.bottom_navigation_item_map).isChecked) {
44+
supportFragmentManager
45+
.beginTransaction()
46+
.replace(R.id.fragment_container, MapsFragment())
47+
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
48+
.commit()
49+
}
4450
true
4551
}
4652

4753
R.id.bottom_navigation_item_profile -> {
48-
supportFragmentManager
49-
.beginTransaction()
50-
.replace(R.id.fragment_container, ProfileFragment())
51-
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
52-
.commit()
54+
if (!bottomNavigation.menu.findItem(R.id.bottom_navigation_item_profile).isChecked) {
55+
supportFragmentManager
56+
.beginTransaction()
57+
.replace(R.id.fragment_container, ProfileFragment())
58+
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
59+
.commit()
60+
}
5361
true
5462
}
5563

@@ -62,13 +70,33 @@ class MainActivity : AppCompatActivity() {
6270
}
6371
}
6472

73+
private fun logoutUserObserver() {
74+
val observer = Observer<Boolean> {
75+
when (it) {
76+
true -> {
77+
Log.d("Profile", "firebaseUser is not null")
78+
}
79+
80+
false -> {
81+
Log.d("Profile", "firebaseUser is null")
82+
val intent = Intent(this, MainActivity::class.java)
83+
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
84+
startActivity(intent)
85+
}
86+
}
87+
}
88+
// set LifeCycle owner with MainActivity. Observe will be destroyed when MainActivity is destroyed
89+
signInVM.getFirebaseAuthLogStatusLiveData().observe(this, observer)
90+
}
91+
6592
private fun checkLogin() {
6693
when (signInVM.isLogIn()) {
6794
true -> {
6895
Log.d(MAIN_ACTIVITY_TAG, "Already login")
6996
setupNavigationBar()
7097
// Init Profile
7198
profileVM.initAppUser(signInVM.getFirebaseAuthCurUser()!!)
99+
logoutUserObserver()
72100
}
73101

74102
false -> {

android/canonical/app/src/main/java/com/google/samples/quickstart/canonical/ProfileFragment.kt

Lines changed: 7 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
package com.google.samples.quickstart.canonical
22

3-
import android.content.Intent
43
import android.os.Bundle
54
import android.util.Log
65
import android.view.LayoutInflater
76
import android.view.View
87
import android.view.ViewGroup
9-
import android.widget.Button
108
import android.widget.ImageButton
119
import android.widget.ListView
1210
import androidx.fragment.app.Fragment
@@ -20,7 +18,6 @@ class ProfileFragment : Fragment() {
2018

2119
private val signInVM: SignInViewModel by activityViewModels()
2220
private val profileVM : ProfileViewModel by activityViewModels()
23-
private lateinit var observer : Observer<Boolean>
2421
private lateinit var binding : FragmentProfileBinding
2522

2623
private fun downloadPhotoAndSetView(view: View) {
@@ -40,29 +37,6 @@ class ProfileFragment : Fragment() {
4037
runHistoryListView?.adapter = runHistoryAdapter
4138
}
4239

43-
override fun onCreate(savedInstanceState: Bundle?) {
44-
super.onCreate(savedInstanceState)
45-
// Add login status change listener.
46-
// When firebaseUser is null, signing out successfully
47-
observer = Observer {
48-
when (it) {
49-
true -> {
50-
Log.d(PROFILE_TAG, "firebaseUser is not null")
51-
}
52-
53-
false -> {
54-
Log.d(PROFILE_TAG, "firebaseUser is null")
55-
val intent = Intent(context, MainActivity::class.java)
56-
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
57-
startActivity(intent)
58-
}
59-
}
60-
}
61-
// set LifeCycle owner with MeFragment. Observe will be destroyed when MeFragment is destroyed
62-
signInVM.getFirebaseAuthLogStatusLiveData().observe(this, observer)
63-
64-
}
65-
6640
override fun onCreateView(
6741
inflater: LayoutInflater, container: ViewGroup?,
6842
savedInstanceState: Bundle?
@@ -81,9 +55,15 @@ class ProfileFragment : Fragment() {
8155
// Sign out both Google account and Firebase
8256
signInVM.signOut()
8357
}
58+
val refreshButton : ImageButton = view.findViewById(R.id.refresh_button)
59+
refreshButton.setOnClickListener {
60+
profileVM.refreshUser(view.findViewById<ListView>(R.id.run_history_list_view).adapter
61+
as RunHistoryAdapter)
62+
downloadPhotoAndSetView(view)
63+
}
64+
setRunHistory()
8465
// update UI
8566
downloadPhotoAndSetView(view)
86-
setRunHistory()
8767
}
8868

8969
companion object {

android/canonical/app/src/main/java/com/google/samples/quickstart/canonical/ProfileViewModel.kt

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ class ProfileViewModel : ViewModel() {
3939
private lateinit var runCollectionRef : CollectionReference
4040
private lateinit var curAppUser: AppUser
4141
private var runHistoryListForView: ArrayList<SingleRun> = ArrayList()
42+
private var totalEnergyCaloriesMutableLiveDataString : MutableLiveData<String> = MutableLiveData("")
43+
private var totalTimeMutableLiveDataString : MutableLiveData<String> = MutableLiveData("")
44+
4245

4346
private fun getUid() : String {
4447
return curAppUser.uid
@@ -51,6 +54,7 @@ class ProfileViewModel : ViewModel() {
5154
private fun getRunHistoryList() : ArrayList<HashMap<String, Any>> {
5255
val reversedRunHistory = curAppUser.runHistoryList
5356
reversedRunHistory.reverse()
57+
Log.d(PROFILE_VM_TAG, "size ${reversedRunHistory.size}")
5458
return reversedRunHistory
5559
}
5660

@@ -66,6 +70,14 @@ class ProfileViewModel : ViewModel() {
6670
curAppUser.totalTimeMillisecond.value = totalTimeMillisecond
6771
}
6872

73+
private fun setTotalEnergyCaloriesString() {
74+
totalEnergyCaloriesMutableLiveDataString.value = curAppUser.totalEnergyCalories.value.toString()
75+
}
76+
77+
private fun setTotalTimeString() {
78+
totalTimeMutableLiveDataString.value = convertMStoStringHMS(curAppUser.totalTimeMillisecond.value ?: 0)
79+
}
80+
6981
private fun setRunHistoryList(runHistoryList : ArrayList<HashMap<String, Any>>) {
7082
curAppUser.runHistoryList = runHistoryList
7183
}
@@ -92,15 +104,22 @@ class ProfileViewModel : ViewModel() {
92104
return millionSeconds.div(4500)
93105
}
94106

95-
private fun syncAppUserStatistic() {
107+
private fun syncAppUserStatistic(adapter: RunHistoryAdapter? = null) {
96108
runUserDocRef.get()
97109
.addOnSuccessListener {document ->
98-
Log.d(PROFILE_VM_TAG, "Get doc successfully")
99-
setTotalDistanceMeters(document.data!![KEY_TOTAL_DIS_M] as Long)
100-
setTotalEnergyCalories(document.data!![KEY_TOTAL_EN_CAL] as Long)
101-
setTotalTimeMillisecond(document.data!![KEY_TOTAL_TIME_MS] as Long)
102-
setRunHistoryList(document.data!![KEY_RUN_HISTORY] as ArrayList<HashMap<String, Any>>)
103-
setRunHistoryListForView()
110+
if (document != null) {
111+
Log.d(PROFILE_VM_TAG, "Get doc successfully")
112+
setTotalDistanceMeters(document.data!![KEY_TOTAL_DIS_M] as Long)
113+
setTotalEnergyCalories(document.data!![KEY_TOTAL_EN_CAL] as Long)
114+
setTotalTimeMillisecond(document.data!![KEY_TOTAL_TIME_MS] as Long)
115+
setRunHistoryList(document.data!![KEY_RUN_HISTORY] as ArrayList<HashMap<String, Any>>)
116+
setRunHistoryListForView()
117+
setTotalEnergyCaloriesString()
118+
setTotalTimeString()
119+
adapter?.notifyDataSetChanged()
120+
} else {
121+
Log.d(PROFILE_VM_TAG, "No such user")
122+
}
104123
}
105124
.addOnFailureListener {
106125
Log.w(PROFILE_VM_TAG, "Get doc Failed")
@@ -119,13 +138,12 @@ class ProfileViewModel : ViewModel() {
119138
return curAppUser.googleAccountProfileUrl
120139
}
121140

122-
fun getTimeHMSString() : String {
123-
val ms = getTotalTimeMillisecond()
124-
return ms ?.let { convertMStoStringHMS(ms) } ?: run { DEFAULT_TIME }
141+
fun getTimeHMSMutableLiveData() : MutableLiveData<String> {
142+
return totalTimeMutableLiveDataString
125143
}
126144

127-
fun getTotalEnergyCaloriesString() : String {
128-
return curAppUser.totalEnergyCalories.value.toString()
145+
fun getTotalEnergyCaloriesMutableLiveData() : MutableLiveData<String> {
146+
return totalEnergyCaloriesMutableLiveDataString
129147
}
130148

131149
fun getRunHistoryListForView(): ArrayList<SingleRun> {
@@ -141,37 +159,35 @@ class ProfileViewModel : ViewModel() {
141159
syncAppUserStatistic()
142160
}
143161

144-
fun uploadNewRecord(singleRunningTimeMillionSeconds : Long, timestamp : String) {
162+
fun refreshUser(adapter: RunHistoryAdapter) {
163+
syncAppUserStatistic(adapter)
164+
}
145165

146-
val newTotalTimeMillisecond = getTotalTimeMillisecond()?.plus(
147-
singleRunningTimeMillionSeconds
148-
)
166+
fun uploadNewRecord(singleRunningTimeMillionSeconds : Long, timestamp : String) {
149167

150-
val newTotalCalories = calculateCalories(newTotalTimeMillisecond ?: 0)
168+
val singleRunningCalories = calculateCalories(singleRunningTimeMillionSeconds ?: 0)
151169

152-
Log.d(PROFILE_VM_TAG, "newTotalTimeMillisecond $newTotalTimeMillisecond")
170+
Log.d(PROFILE_VM_TAG, "newTotalTimeMillisecond $singleRunningTimeMillionSeconds")
153171

154172
val singleRunData = hashMapOf(
155173
KEY_SINGLE_RUN_TIME to singleRunningTimeMillionSeconds,
156174
KEY_SINGLE_RUN_TIMESTAMP to timestamp
157175
)
158176

159177
val updateRunUserData = hashMapOf(
160-
KEY_TOTAL_TIME_MS to newTotalTimeMillisecond,
161-
KEY_TOTAL_EN_CAL to newTotalCalories,
178+
KEY_TOTAL_TIME_MS to FieldValue.increment(singleRunningTimeMillionSeconds),
179+
KEY_TOTAL_EN_CAL to FieldValue.increment(singleRunningCalories),
162180
KEY_RUN_HISTORY to FieldValue.arrayUnion(singleRunData)
163181
)
164182

165183

166184
Firebase.firestore.runBatch { batch ->
167-
batch.update(runUserDocRef, updateRunUserData)
185+
batch.update(runUserDocRef, updateRunUserData as Map<String, Any>)
168186

169187
}
170188
.addOnSuccessListener {
171189
Log.d(PROFILE_VM_TAG, "Upload record successfully")
172190
syncAppUserStatistic()
173-
// No need to call Adapter.notifyDataSetChanged()
174-
// Each time we access profile page, just create a new one.
175191
}
176192
}
177193

android/canonical/app/src/main/java/com/google/samples/quickstart/canonical/SignInViewModel.kt

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,7 @@ class SignInViewModel : ViewModel() {
5959
private fun firebaseSignOutInit() {
6060
Log.d(SIGN_IN_VM_TAG, "firebaseSignOutInit")
6161
authStateListenerForSignOut = FirebaseAuth.AuthStateListener {
62-
it.currentUser ?. let {
63-
Log.w(SIGN_IN_VM_TAG, "firebaseSignOut Failed")
64-
Toast.makeText(context, context.getString(R.string.sign_out_failed), Toast.LENGTH_SHORT).show()
65-
} ?: run {
62+
it.currentUser ?: let {
6663
Log.w(SIGN_IN_VM_TAG, "firebaseSignOut Succeed")
6764
curFirebaseUser.value!!.firebaseUser.value = null
6865
curFirebaseUser.value!!.isLogin.value = false
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:width="24dp"
3+
android:height="24dp"
4+
android:viewportWidth="24"
5+
android:viewportHeight="24"
6+
android:tint="?attr/colorControlNormal">
7+
<path
8+
android:fillColor="@android:color/white"
9+
android:pathData="M17.65,6.35C16.2,4.9 14.21,4 12,4c-4.42,0 -7.99,3.58 -7.99,8s3.57,8 7.99,8c3.73,0 6.84,-2.55 7.73,-6h-2.08c-0.82,2.33 -3.04,4 -5.65,4 -3.31,0 -6,-2.69 -6,-6s2.69,-6 6,-6c1.66,0 3.14,0.69 4.22,1.78L13,11h7V4l-2.35,2.35z"/>
10+
</vector>

android/canonical/app/src/main/res/layout/fragment_profile.xml

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@
9393
android:layout_height="wrap_content"
9494
android:layout_marginBottom="5dp"
9595
android:fontFamily="sans-serif-light"
96-
android:text="@{profileViewModel.getTimeHMSString()}"
96+
android:text="@{profileViewModel.getTimeHMSMutableLiveData()}"
9797
android:textColor="@android:color/white"
9898
android:textSize="30sp" />
9999

@@ -132,7 +132,7 @@
132132
android:layout_marginBottom="5dp"
133133
android:gravity="center"
134134
android:fontFamily="sans-serif-light"
135-
android:text="@{profileViewModel.getTotalEnergyCaloriesString()}"
135+
android:text="@{profileViewModel.getTotalEnergyCaloriesMutableLiveData()}"
136136
android:textColor="@android:color/white"
137137
android:textSize="30sp" />
138138

@@ -152,6 +152,16 @@
152152

153153
</LinearLayout>
154154

155+
<ImageButton
156+
android:id="@+id/refresh_button"
157+
android:layout_width="40dp"
158+
android:layout_height="40dp"
159+
android:layout_margin="15dp"
160+
android:background="@android:color/transparent"
161+
android:src="@drawable/ic_baseline_refresh_24"
162+
app:layout_constraintStart_toStartOf="parent"
163+
app:layout_constraintTop_toTopOf="parent" />
164+
155165
<ImageButton
156166
android:id="@+id/logout_button"
157167
android:layout_width="40dp"
@@ -166,8 +176,9 @@
166176
android:id="@+id/run_history_list_view"
167177
android:layout_width="match_parent"
168178
android:layout_height="0dp"
169-
app:layout_constraintVertical_weight="1"
170-
app:layout_constraintTop_toBottomOf="@+id/usr_statistic_bar"/>
179+
app:layout_constraintBottom_toBottomOf="parent"
180+
app:layout_constraintTop_toBottomOf="@+id/usr_statistic_bar"
181+
app:layout_constraintVertical_weight="1" />
171182

172183
</androidx.constraintlayout.widget.ConstraintLayout>
173184
</layout>

android/canonical/app/src/main/res/values/strings.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
<string name="cannot_access_location">Cannot access location now. Please Try later</string>
1515
<string name="logout_button_text">Logout</string>
1616
<string name="sign_out_failed">SignOut Failed. Please try again.</string>
17-
<string name="login_failed">Login Failed. Please try it later.</string>
17+
<string name="login_failed">Login Failed. Please try it again.</string>
1818
<string name="total_time">TOTAL TIME</string>
1919
<string name="total_energy">CALORIES</string>
2020
<string name="usr_run_energy">240</string>

0 commit comments

Comments
 (0)