如何构建Android MVVM应用程序

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何构建Android MVVM应用程序相关的知识,希望对你有一定的参考价值。

参考技术A 可以使用框架,参考内容如下:
1、概述
Databinding
是一种框架,MVVM是一种模式,两者的概念是不一样的。咱的理解DataBinding是一个实现数据和UI绑定的框架,只是一个实现MVVM模式的工具。ViewModel和View可以通过DataBinding来实现单向绑定和双向绑定,这套UI和数据之间的动态监听和动态更新的框架Google已经帮咱们做好了。在MVVM模式中ViewModel和View是用绑定关系来实现的,所以有了DataBinding
使咱们构建android
MVVM
应用程序成为可能。
之前看了很多关于DataBinding的博客和相关的一些Demo,大多数就是往xml布局文件传入一些数据,然后把这些数据绑定到控件上(
如TextView
binding:text=“@user.name
),接着在这些控件上(如Button
binding:setOnClickListener=”@user.listener”)
设置一些事件到控件上,基本讲述都是DataBinding的基本用法。但是并没有人告诉把一个onClickListener
写到一个类并把这个listener绑定到xml里面上是不是不太好,也没有人告诉这个和xml布局绑定的ViewModel类应该放哪些数据,应该做什么事?应该如何设计?更是很少有博文来告诉在Android
中如何通过Data
Binding
去构建MVVM
的应用框架。这也就是是本篇文章的重点。接下来,咱们先来看看什么是MVVM,然后在一步一步来设计整个应用程序框架。

如何使用 MVVM 架构实现 Firebase Google SignIn?

【中文标题】如何使用 MVVM 架构实现 Firebase Google SignIn?【英文标题】:How to implement Firebase Google SignIn with MVVM architecture? 【发布时间】:2019-10-20 18:46:13 【问题描述】:

我正在构建一个应用程序,但我目前面临一个问题:我按照google guide 在 LoginActivity 中编写了我的 Google/Facebook 登录按钮的所有事件。但是,我不想将业务代码保留在活动中以遵循 MVVM 架构。因此,如何放置 Firebase 方法(需要活动引用和生命周期回调)?

我尝试了一个正在运行的 LoginViewModel,但它引用了 LoginActivity

class LoginViewModel(application: Application) : BaseViewModelContext(application) 

    lateinit var auth: FirebaseAuth
    val Tag: String = LoginViewModel::class.java.simpleName;
    val gso: GoogleSignInOptions
    val googleSignInClient: GoogleSignInClient

    init 
        auth = FirebaseAuth.getInstance()
        gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestIdToken(application.getString(R.string.default_client_id))
            .build()

        googleSignInClient = GoogleSignIn.getClient(application, gso)
    



    fun activityForResultLogin(requestCode:Int, resultCode: Int, data: Intent?, activity: Activity)
        if(requestCode == Constants.RC_SIGN_IN)
            val task = GoogleSignIn.getSignedInAccountFromIntent(data)
            try 
                // Google Sign In was successful, authenticate with Firebase
                val account = task.getResult(ApiException::class.java)
                firebaseAuthWithGoogle(account!!, activity)
             catch (e: ApiException) 
                // Google Sign In failed, update UI appropriately
                Log.w(Tag, "Google sign in failed", e)
                // ...
            
        
    

    private fun firebaseAuthWithGoogle(acct: GoogleSignInAccount, activity: Activity) 
        Log.d(Tag, "firebaseAuthWithGoogle:" + acct.id!!)

        val credential = GoogleAuthProvider.getCredential(acct.idToken, null)
        auth.signInWithCredential(credential)
            .addOnCompleteListener(activity)  task ->
                if (task.isSuccessful) 
                    // Sign in success, update UI with the signed-in user's information
                    Log.d(Tag, "signInWithCredential:success")
                    val user = auth.currentUser
                    activity.shortToast("SignInSuccess")
                 else 
                    // If sign in fails, display a message to the user.
                    Log.w(Tag, "signInWithCredential:failure", task.exception)
                    activity.shortToast("SignInFailed")
                

            
    

    fun signInGoogle(activity: Activity)
        val signInIntent = googleSignInClient.signInIntent
        activity.startActivityForResult(signInIntent, Constants.RC_SIGN_IN)
    

    fun signOutGoogle(activity: Activity)
        googleSignInClient.signOut().addOnCompleteListener(activity)
            //Update ui
        
    

【问题讨论】:

看看 Paha 实现 GoogleSignIn 的实现:github.com/jojink/Android-Kotlin-FirebaseAuth/blob/feature/…希望这会有所帮助。 那个 git 看起来更像 MVP no MVVM 如果您对干净的 Firebase 身份验证感兴趣,可以查看此article。 在 codelab github.com/googlecodelabs/android-kotlin-logingoogle 上查看这个例子 你好@ELTEGANIMOHAMED!谢谢 !这正是我想要的:) 【参考方案1】:

这是我所做的。

创建用户模型:

data class User(
    val uid: String,
    val name: String?,
    val email: String?,
    var isAuthenticated: Boolean = false,
    var isNew: Boolean? = false,
    var isCreated: Boolean = false

) : Serializable

    constructor() : this("","","") 

    


创建 AuthRepository 类:

class AuthRepository 

    private val firebaseAuth: FirebaseAuth = FirebaseAuth.getInstance()
    private val rootRef: FirebaseFirestore = FirebaseFirestore.getInstance()
    private val usersRef: CollectionReference = rootRef.collection(USERS)

    // Sign in using google
    fun firebaseSignInWithGoogle(googleAuthCredential: AuthCredential): MutableLiveData<ResponseState<User>> 
        val authenticatedUserMutableLiveData: MutableLiveData<ResponseState<User>> =
            MutableLiveData()
       
         firebaseAuth.signInWithCredential(googleAuthCredential).addOnCompleteListener  authTask ->
            if (authTask.isSuccessful) 
                var isNewUser = authTask.result?.additionalUserInfo?.isNewUser
                val firebaseUser: FirebaseUser? = firebaseAuth.currentUser
                if (firebaseUser != null) 
                    val uid = firebaseUser.uid
                    val name = firebaseUser.displayName
                    val email = firebaseUser.email
                    val user = User(uid = uid, name = name, email = email)
                    user.isNew = isNewUser
                    authenticatedUserMutableLiveData.value = ResponseState.Success(user)

                


             else 

                authenticatedUserMutableLiveData.value = authTask.exception?.message?.let 
                    ResponseState.Error(it)
                

            


        
        return authenticatedUserMutableLiveData
    


创建 LoginViewModel 类:

class LoginViewModel constructor(private val authRepository: AuthRepository) :
    ViewModel() 

    private var _authenticateUserLiveData: MutableLiveData<ResponseState<User>> = MutableLiveData()
  val authenticateUserLiveData: LiveData<ResponseState<User>> get() = _authenticateUserLiveData

    fun signInWithGoogle(googleAuthCredential: AuthCredential) 
        _authenticateUserLiveData = authRepository.firebaseSignInWithGoogle(googleAuthCredential)
    



这里的ResponseState类如下:

sealed class ResponseState<T>(
    val data: T? = null,
    val message: String? = null
) 


    class Success<T>(data: T) : ResponseState<T>(data)
    class Error<T>(message: String) : ResponseState<T>(message = message)
    class Loading<T> : ResponseState<T>()


在您的活动或片段中,您可以将其用作:

lateinit var googleSignInClient: GoogleSignInClient
private fun initGoogleSignInClient() 
    val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
        .requestIdToken(getString(R.string.default_web_client_id))
        .requestEmail()
        .build()

    googleSignInClient = GoogleSignIn.getClient(this, gso)


private fun signInUsingGoolge() 
    val signInGoogleIntent = (activity as MainActivity).googleSignInClient.signInIntent
    startActivityForResult(signInGoogleIntent, RC_SIGN_IN)

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent ? ) 
    super.onActivityResult(requestCode, resultCode, data)

    if (requestCode == RC_SIGN_IN) 
        val task = GoogleSignIn.getSignedInAccountFromIntent(data)
        try 
            // Google Sign In was successful, authenticate with Firebase
            val account = task.getResult(ApiException::class.java) !!
                if (account != null) 
                    getGoogleAuthCredential(account)
                

         catch (e: ApiException) 
            // Google Sign In failed, update UI appropriately
        
    


private fun getGoogleAuthCredential(account: GoogleSignInAccount) 
    binding.progressBar.visible()
    val googleTokeId = account.idToken
    val googleAuthCredential = GoogleAuthProvider.getCredential(googleTokeId, null)
    signInWithGoogleAuthCredential(googleAuthCredential)


private fun signInWithGoogleAuthCredential(googleAuthCredential: AuthCredential) 

    loginViewModel.signInWithGoogle(googleAuthCredential)
    loginViewModel.authenticateUserLiveData.observe(viewLifecycleOwner, 
        authenticatedUser - >
        when(authenticatedUser) 
            is ResponseState.Error - > 
                authenticatedUser.message ? .let 
                    context ? .toast(it)
                
            
            is ResponseState.Success - > 
                if (authenticatedUser.data != null)
                //update ui
            
            is ResponseState.Loading - > 
                //show progress
            
        
    )

 
      

【讨论】:

以上是关于如何构建Android MVVM应用程序的主要内容,如果未能解决你的问题,请参考以下文章

如何构建Android MVVM应用程序

《Android构建MVVM》系列 之 MVVM架构快速入门

Android MVVM startActivity 的最佳实践

使用Architecture Components构建的应用程序是否使其成为“MVVM”,如果是,应用程序的哪些部分与哪个MVVM层相关?

如何在 Android MVVM ViewModel 中获取上下文

Android MVVM 设计模式示例