FirebaseAuth.AuthStateListener 使用 LiveData。下面的实现有改进的余地吗?

Posted

技术标签:

【中文标题】FirebaseAuth.AuthStateListener 使用 LiveData。下面的实现有改进的余地吗?【英文标题】:FirebaseAuth.AuthStateListener using LiveData. Is there scope for improvement in below implementation? 【发布时间】:2018-10-06 17:39:34 【问题描述】:

在实施架构组件方面是否有改进的余地 或一般考虑:

    Note:如果您选择使用 AuthStateListener,请确保在启动 FirebaseUI 流程之前取消注册,并在流程返回后重新注册。 FirebaseUI 在内部执行身份验证操作,这可能会在流程完成之前触发侦听器。

实时数据

public class FirebaseAuthLiveData extends LiveData<FirebaseUser> 
    private FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();

    private FirebaseAuth.AuthStateListener authStateListener = 
            new FirebaseAuth.AuthStateListener() 
                @Override
                public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) 
                    FirebaseUser firebaseUser = firebaseAuth.getCurrentUser();
                    setValue(firebaseUser);
                
            ;

    @Override
    protected void onActive() 
        super.onActive();
        firebaseAuth.addAuthStateListener(authStateListener);
    

    @Override
    protected void onInactive() 
        super.onInactive();
        firebaseAuth.removeAuthStateListener(authStateListener);
    

视图模型

public class FirebaseAuthViewModel extends ViewModel 
    private final FirebaseAuthLiveData firebaseAuthLiveData = new 
            FirebaseAuthLiveData();

    public LiveData<FirebaseUser> getFirebaseAuthLiveData() 
        return firebaseAuthLiveData; 
    

主要活动

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    FirebaseAuthViewModel firebaseAuthViewModel = 
    ViewModelProviders.of(MainActivity.this).get(FirebaseAuthViewModel.class);

    firebaseUserLiveData = firebaseAuthViewModel.getFirebaseAuthLiveData();

    firebaseUserLiveData.observe(MainActivity.this, new Observer<FirebaseUser>() 
        @Override
        public void onChanged(@Nullable FirebaseUser firebaseUser) 
            if (firebaseUser == null) 
                final Intent intent = AuthUI.getInstance().createSignInIntentBuilder()
                        .setAvailableProviders(Collections.singletonList(                            
                            new AuthUI.IdpConfig.Builder(AuthUI.GOOGLE_PROVIDER).build())
                        ).build();
                startActivityForResult(intent, SIGN_IN);
             else 
                updateUI(firebaseUser);
            

        
    );

【问题讨论】:

这个实现是一个好的架构设计吗?我正在使用 ViewModel 和 LiveData 实现 FirebaseAuth,您的代码对我来说似乎简单明了。 我也想知道这是否是实现 authstatelistener 的正确方法.. 这种方法工作正常吗?.. 似乎将 firestore 存储库与身份验证分开,我猜这仍然符合要求使用 MVVM.. 【参考方案1】:

你快到了。您遇到的唯一问题是在活动中使用“FirebaseUser”对象,这打破了 MVVM 架构模式,据说活动应该对它的数据源一无所知

所以最简单和最干净的解决方案可能是使用 LiveData 类:

class AuthLiveData(
    private val auth: FirebaseAuth
): LiveData<Boolean>(), FirebaseAuth.AuthStateListener 
    override fun onAuthStateChanged(auth: FirebaseAuth) 
        value = auth.currentUser == null
    

    override fun onActive() 
        super.onActive()
        auth.addAuthStateListener(this)
    

    override fun onInactive() 
        super.onInactive()
        auth.removeAuthStateListener(this)
    

还有一个存储库类:

class MyRepository 
    private val auth = FirebaseAuth.getInstance()

    fun getFirebaseAuthState(): AuthLiveData 
        return AuthLiveData(auth)
    

现在在 ViewModel 类中,我们可以简单地:

class MyViewModel: ViewModel() 
    val repository = MyRepository()

    fun getAuthState(): LiveData<Boolean> 
        return repository.getFirebaseAuthState()
    

最后,在activity中我们可以观察到auth state的变化是这样的:

viewModel.getAuthState().observe(this,  isUserSignedOut ->
    if (isUserSignedOut) 
        //Update the UI
    
)

这意味着我们将始终知道用户何时登录,而不知道哪个是后端。

【讨论】:

以上是关于FirebaseAuth.AuthStateListener 使用 LiveData。下面的实现有改进的余地吗?的主要内容,如果未能解决你的问题,请参考以下文章