Browse Source

@fun: use flow

bai 2 years ago
parent
commit
858aed7559

+ 7 - 8
app/src/main/java/com/ys/bdtp/adm/mvvm/model/db/dao/UserDao.kt

@@ -24,16 +24,12 @@ interface UserDao {
     @Query("select * from user")
     suspend fun getUsers(): List<UserEntity>
 
-    @Query("select * from user")
-    fun getUsers1(): Flow<List<UserEntity>>
-
     /**
      * 获取当前登录用户
      */
     @Query("select * from user where state = 1")
     suspend fun currentUser(): UserEntity?
 
-
     @Query("select * from user where state = 1")
     fun getUser(): Flow<UserEntity?>
 
@@ -50,11 +46,14 @@ interface UserDao {
     fun delUser(user: UserEntity)
 
     @Transaction
-    @Query("select * from user")
-    fun getUserWithProjects(): List<UserWithProjects>
-
-    @Transaction
     @Query("select * from user where id = :id")
     suspend fun getUserWithProjectsById(id: String): UserWithProjects
 
+    /**
+     * 获取 User, Project 一对多
+     */
+    @Transaction
+    @Query("select * from user where state = 1")
+    fun getUserWithProjects(): Flow<UserWithProjects>
+
 }

+ 2 - 1
app/src/main/java/com/ys/bdtp/adm/mvvm/model/db/dao/task/ProjectDao.kt

@@ -2,6 +2,7 @@ package com.ys.bdtp.adm.mvvm.model.db.dao.task
 
 import androidx.room.*
 import com.ys.bdtp.adm.mvvm.model.db.entity.task.ProjectEntity
+import kotlinx.coroutines.flow.Flow
 
 /**
  * project 表访问接口
@@ -11,7 +12,7 @@ import com.ys.bdtp.adm.mvvm.model.db.entity.task.ProjectEntity
 interface ProjectDao {
 
     @Query("select * from project")
-    suspend fun getProjects(): List<ProjectEntity>
+    fun getProjects(): Flow<List<ProjectEntity>>
 
     @Query("select * from project where id = :id")
     suspend fun getProjectById(id: String): ProjectEntity

+ 11 - 9
app/src/main/java/com/ys/bdtp/adm/mvvm/model/nt/Http.kt

@@ -38,15 +38,17 @@ suspend fun <T> request(
     success: suspend (T) -> Unit,
     failure: (Fail) -> Unit,
 ) {
-    runCatching {
-        request()
-    }.onSuccess {
-        if (it.result == "success") {
-            success(it.data)
-        } else {
-            failure(Fail(it.result, it.message ?: "request ok, but no data"))
+    withContext(Dispatchers.IO) {
+        runCatching {
+            request()
+        }.onSuccess {
+            if (it.result == "success") {
+                success(it.data)
+            } else {
+                failure(Fail(it.result, it.message ?: "request ok, but no data"))
+            }
+        }.onFailure {
+            failure(Fail("catch", it.message ?: "request catch and nothing"))
         }
-    }.onFailure {
-        failure(Fail("catch", it.message ?: "request catch and nothing"))
     }
 }

+ 4 - 13
app/src/main/java/com/ys/bdtp/adm/mvvm/ui/screen/flash/Flash.kt

@@ -16,7 +16,8 @@ import androidx.compose.ui.unit.sp
 import com.ys.bdtp.adm.R
 import com.ys.bdtp.adm.app.theme.textBlackColor
 import com.ys.bdtp.adm.mvvm.ui.screen.main.LocalNavHostController
-import com.ys.bdtp.adm.mvvm.ui.screen.main.Route
+import com.ys.bdtp.adm.mvvm.ui.screen.main.flashToLogin
+import com.ys.bdtp.adm.mvvm.ui.screen.main.flashToProject
 import com.ys.bdtp.adm.mvvm.vm.flash.FlashViewModel
 import org.kodein.di.compose.rememberViewModel
 
@@ -31,19 +32,9 @@ fun Flash() {
     LaunchedEffect(Unit) {
         val user = vm.currentUser()
         if (user != null) {
-            nav.navigate(Route.Project) {
-                launchSingleTop = true
-                popUpTo(Route.Flash) {
-                    inclusive = true
-                }
-            }
+            nav.flashToProject()
         } else {
-            nav.navigate(Route.Login) {
-                launchSingleTop = true
-                popUpTo(Route.Flash) {
-                    inclusive = true
-                }
-            }
+            nav.flashToLogin()
         }
     }
 

+ 2 - 6
app/src/main/java/com/ys/bdtp/adm/mvvm/ui/screen/login/LoginContent.kt

@@ -25,7 +25,7 @@ import com.ys.bdtp.adm.app.theme.grayColor
 import com.ys.bdtp.adm.app.theme.textBlackColor
 import com.ys.bdtp.adm.mvvm.model.vo.request.Login
 import com.ys.bdtp.adm.mvvm.ui.screen.main.LocalNavHostController
-import com.ys.bdtp.adm.mvvm.ui.screen.main.Route
+import com.ys.bdtp.adm.mvvm.ui.screen.main.loginToProject
 import com.ys.bdtp.adm.mvvm.vm.login.LoginViewModel
 import kotlinx.coroutines.launch
 import org.kodein.di.compose.rememberInstance
@@ -202,11 +202,7 @@ fun LoginContent() {
                     success = { token ->
                         sp.edit { putString(Token, token) }
                         sp.edit { putString(Password, password) }
-                        nav.navigate(Route.Project) {
-                            popUpTo(Route.Login) {
-                                inclusive = true
-                            }
-                        }
+                        nav.loginToProject()
                     },
                     failure = { fail ->
                         scope.launch {

+ 40 - 1
app/src/main/java/com/ys/bdtp/adm/mvvm/ui/screen/main/Route.kt

@@ -1,5 +1,7 @@
 package com.ys.bdtp.adm.mvvm.ui.screen.main
 
+import androidx.navigation.NavHostController
+
 /**
  * 路由对象
  *
@@ -13,4 +15,41 @@ object Route {
     const val Tasks = "tasks"
     const val Offline = "offline"
     const val Cad = "cad"
-}
+}
+
+/**
+ * Flash 跳转到 Project 界面
+ */
+fun NavHostController.flashToProject() {
+    navigate(Route.Project) {
+        launchSingleTop = true
+        popUpTo(Route.Flash) {
+            inclusive = true
+        }
+    }
+}
+
+/**
+ * Flash 跳转到 Login 界面
+ */
+fun NavHostController.flashToLogin() {
+    navigate(Route.Login) {
+        launchSingleTop = true
+        popUpTo(Route.Flash) {
+            inclusive = true
+        }
+    }
+}
+
+/**
+ * Login 跳转到 Project 界面
+ */
+fun NavHostController.loginToProject() {
+    navigate(Route.Project) {
+        launchSingleTop = true
+        popUpTo(Route.Login) {
+            inclusive = true
+        }
+    }
+
+}

+ 19 - 49
app/src/main/java/com/ys/bdtp/adm/mvvm/ui/screen/project/Project.kt

@@ -1,9 +1,14 @@
 package com.ys.bdtp.adm.mvvm.ui.screen.project
 
+import android.content.SharedPreferences
 import android.net.ConnectivityManager
+import android.util.Log
 import androidx.compose.foundation.ExperimentalFoundationApi
 import androidx.compose.foundation.background
-import androidx.compose.foundation.layout.*
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.wrapContentWidth
 import androidx.compose.runtime.*
 import androidx.compose.ui.Modifier
 import androidx.compose.ui.platform.LocalLifecycleOwner
@@ -11,12 +16,9 @@ import androidx.compose.ui.tooling.preview.Preview
 import androidx.compose.ui.unit.dp
 import androidx.lifecycle.Lifecycle
 import androidx.lifecycle.flowWithLifecycle
-import com.ys.bdtp.adm.app.tools.isNet
+import com.ys.bdtp.adm.app.Password
 import com.ys.bdtp.adm.app.theme.underColor
-import com.ys.bdtp.adm.mvvm.model.nt.FailureResponse
-import com.ys.bdtp.adm.mvvm.model.nt.SuccessResponse
-import com.ys.bdtp.adm.mvvm.model.db.entity.task.ProjectEntity
-import com.ys.bdtp.adm.mvvm.model.db.entity.UserEntity
+import com.ys.bdtp.adm.app.tools.isNet
 import com.ys.bdtp.adm.mvvm.ui.compose.*
 import com.ys.bdtp.adm.mvvm.ui.screen.main.LocalNavHostController
 import com.ys.bdtp.adm.mvvm.ui.screen.main.Route
@@ -34,54 +36,24 @@ fun Project() {
     val nav = LocalNavHostController.current!!
     val vm by rememberViewModel<ProjectViewModel>()
     val cm by rememberInstance<ConnectivityManager>()
+    val sp by rememberInstance<SharedPreferences>()
     val scope = rememberCoroutineScope()
-    // var user by remember { mutableStateOf<UserEntity?>(null) }
-    var projects by remember { mutableStateOf<List<ProjectEntity>>(emptyList()) }
     var popupState by remember { mutableStateOf(false) }
 
     val lifecycleOwner = LocalLifecycleOwner.current
-    /*val userFlow = vm.userFlow
-    val userFlowLifecycleAware = remember(vm.userFlow, lifecycleOwner) {
-        userFlow.flowWithLifecycle(lifecycleOwner.lifecycle, Lifecycle.State.STARTED)
+    val userFlowLifecycleAware = remember(vm.userWithsProjects, lifecycleOwner) {
+        vm.userWithsProjects.flowWithLifecycle(lifecycleOwner.lifecycle, Lifecycle.State.STARTED)
     }
 
-    val user by userFlowLifecycleAware.collectAsState(null, scope.coroutineContext)*/
-    val user by vm.userFlow.collectAsState()
+    val userWithsProjects = userFlowLifecycleAware.collectAsState(null)
 
     LaunchedEffect(Unit) {
-        // isNet 联网,进行网络通信,获取账号信息也判断 token是否能用
+        // isNet 联网,token 进行网络通信, 发起请求, 更新数据.
         if (isNet(cm)) {
-            when (val response = vm.getAccount()) {
-                is SuccessResponse -> {
-                    val account = response.data
-                    vm.setCurrentAccount(account)
-                    val up = vm.getUserWithProjectsById(account.id)
-
-                    projects = up.projects
-                }
-
-                is FailureResponse -> {
-                    val fail = response.fail
-                    if (fail.code == "catch") {
-                        // 提示网络问题
-                    } else {
-                        // 根据不同 code 进行不同操作
-                    }
-                }
-            }
-        } else {
-            // 离线暂时有问题
-            val u = vm.currentUser()
-            if (u == null) {
-                nav.navigate(Route.Login) {
-                    popUpTo(Route.Project) {
-                        inclusive = true
-                    }
-                }
-            } else {
-                val up = vm.getUserWithProjectsById(u.id)
-                //user = up.user
-                projects = up.projects
+            val password = sp.getString(Password, "") ?: ""
+            vm.requestAccount(password) { fail ->
+                // 不同 code 进行不同操作
+                Log.d("Project", "Project requestAccount fail :${fail}")
             }
         }
     }
@@ -89,8 +61,6 @@ fun Project() {
     Column(
         modifier = Modifier.fillMaxSize()
     ) {
-        println("user:::::: $user ")
-        println("user:::::: $user ")
         Head(
             left = {
                 ProjectHeadLeft()
@@ -129,11 +99,11 @@ fun Project() {
                 .background(underColor)
                 .padding(horizontal = 32.dp, vertical = 40.dp)
         ) {
-            if (projects.isEmpty())
+            val projects = userWithsProjects.value?.projects
+            if (projects.isNullOrEmpty())
                 Blank()
             else
                 ProjectContent(projects)
-
         }
     }
 }

+ 30 - 57
app/src/main/java/com/ys/bdtp/adm/mvvm/vm/project/ProjectRepository.kt

@@ -1,18 +1,16 @@
 package com.ys.bdtp.adm.mvvm.vm.project
 
-import com.ys.bdtp.adm.mvvm.model.nt.Response
+import android.util.Log
 import com.ys.bdtp.adm.mvvm.model.db.AdmDatabase
-import com.ys.bdtp.adm.mvvm.model.db.entity.task.ProjectEntity
 import com.ys.bdtp.adm.mvvm.model.db.entity.UserEntity
 import com.ys.bdtp.adm.mvvm.model.db.entity.relation.UserWithProjects
 import com.ys.bdtp.adm.mvvm.model.nt.Api
+import com.ys.bdtp.adm.mvvm.model.nt.Fail
 import com.ys.bdtp.adm.mvvm.model.nt.request
-import com.ys.bdtp.adm.mvvm.model.vo.request.Account
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.withContext
 
-
 /**
  * ProjectRepository
  *
@@ -24,64 +22,39 @@ class ProjectRepository(private val api: Api, private val db: AdmDatabase) {
     /**
      * 获取账号信息
      */
-    suspend fun getAccount(): Response<Account> {
-        return withContext(Dispatchers.IO) {
-            request {
-                api.getAccount()
+    suspend fun requestAccount(password: String, failure: (Fail) -> Unit) {
+        request(
+            request = { api.getAccount() },
+            success = { account ->
+                val user = UserEntity(
+                    password = password,
+                    state = 1,
+                    id = account.id,
+                    account = account.account,
+                    deptId = account.deptId,
+                    email = account.email,
+                    phone = account.phone,
+                    name = account.name,
+                )
+                val users = db.userDao().getUsers().onEach { u -> u.state = 0 }.toMutableList()
+                users.add(user)
+                db.userDao().insUsers(users)
+                account.projects.forEach { it.userId = user.id }
+                db.projectDao().insProjects(account.projects)
+                Log.d("requestAccount", "requestAccount success")
+            },
+            failure = { fail ->
+                failure(fail)
+                Log.d("requestAccount", "requestAccount failure : $fail")
             }
-        }
-    }
-
-    /**
-     * 获取项目信息
-     */
-    suspend fun getProjects(): List<ProjectEntity> {
-        return withContext(Dispatchers.IO) {
-            db.projectDao().getProjects()
-        }
-    }
-
-    /**
-     * 设置当前账号信息
-     */
-    suspend fun setCurrentAccount(account: Account) {
-        return withContext(Dispatchers.IO) {
-            val user = UserEntity(
-                password = "",
-                state = 1,
-                id = account.id,
-                account = account.account,
-                deptId = account.deptId,
-                email = account.email,
-                phone = account.phone,
-                name = account.name,
-            )
-            val users = db.userDao().getUsers().onEach { u -> u.state = 0 }
-            db.userDao().insUsers(users)
-            db.userDao().insUser(user)
-            account.projects.forEach { it.userId = user.id }
-            db.projectDao().insProjects(account.projects)
-        }
-    }
-
-    suspend fun getUserWithProjectsById(id: String): UserWithProjects {
-        return withContext(Dispatchers.IO) {
-            db.userDao().getUserWithProjectsById(id)
-        }
+        )
     }
 
     /**
-     * 获取当前登录的用户
+     *  获取用户以及用户项目
      */
-    suspend fun getCurrentUser(): UserEntity? {
-        return withContext(Dispatchers.IO) {
-            db.userDao().currentUser()
-        }
-    }
-
-    fun getUser(): Flow<UserEntity?> {
-        val flow = db.userDao().getUser()
-        return flow
+    fun getUserWithProjects(): Flow<UserWithProjects> {
+        return db.userDao().getUserWithProjects()
     }
 
     suspend fun logout() {

+ 9 - 49
app/src/main/java/com/ys/bdtp/adm/mvvm/vm/project/ProjectViewModel.kt

@@ -3,17 +3,7 @@ package com.ys.bdtp.adm.mvvm.vm.project
 import androidx.lifecycle.ViewModel
 import androidx.lifecycle.viewModelScope
 import com.ys.bdtp.adm.mvvm.model.nt.Fail
-import com.ys.bdtp.adm.mvvm.model.nt.FailureResponse
-import com.ys.bdtp.adm.mvvm.model.nt.Response
-import com.ys.bdtp.adm.mvvm.model.nt.SuccessResponse
-import com.ys.bdtp.adm.mvvm.model.db.entity.task.ProjectEntity
-import com.ys.bdtp.adm.mvvm.model.db.entity.UserEntity
-import com.ys.bdtp.adm.mvvm.model.db.entity.relation.UserWithProjects
-import com.ys.bdtp.adm.mvvm.model.vo.request.Account
-import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.SharingStarted.Companion.WhileSubscribed
-import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.flow
 import kotlinx.coroutines.flow.stateIn
 import kotlinx.coroutines.launch
 
@@ -27,58 +17,28 @@ import kotlinx.coroutines.launch
 class ProjectViewModel(private val repo: ProjectRepository) : ViewModel() {
 
     /**
-     * 获取项目信息
+     * 当前用于和项目
      */
-    suspend fun getProjects(): List<ProjectEntity> {
-        return repo.getProjects()
-    }
+    val userWithsProjects = repo.getUserWithProjects().stateIn(
+        scope = viewModelScope,
+        started = WhileSubscribed(5000),
+        initialValue = null
+    )
 
     /**
      * 获取账号信息
      */
-    suspend fun getAccount(success: (Account) -> Unit, failure: (Fail) -> Unit) {
+    fun requestAccount(password: String, failure: (Fail) -> Unit) {
         viewModelScope.launch {
-            when (val response = repo.getAccount()) {
-                is SuccessResponse -> {
-                    success(response.data)
-                }
-                is FailureResponse -> {
-                    failure(response.fail)
-                }
-            }
+            repo.requestAccount(password, failure)
         }
     }
 
     /**
-     * 获取账号信息
+     * 退出
      */
-    suspend fun getAccount(): Response<Account> {
-        return repo.getAccount()
-    }
-
-    suspend fun setCurrentAccount(account: Account) {
-        repo.setCurrentAccount(account)
-    }
-
-    /**
-     * 获取用户与项目一对多关系
-     */
-    suspend fun getUserWithProjectsById(id: String): UserWithProjects {
-        return repo.getUserWithProjectsById(id)
-    }
-
-    suspend fun currentUser(): UserEntity? {
-        return repo.getCurrentUser()
-    }
-
     suspend fun logout() {
         repo.logout()
     }
 
-    val userFlow: StateFlow<UserEntity?> = repo.getUser().stateIn(
-        scope = viewModelScope,
-        started = WhileSubscribed(5000),
-        initialValue = null
-    )
-
 }