Android ViewModel调用Activity方法

问题描述 投票:9回答:2

我正在我的项目中使用android AAC库和Android数据绑定库。我有AuthActivity和AuthViewModel扩展了android的ViewModel类。在某些情况下,我需要让Activity为ViewModel调用一些方法。例如,当用户点击Google Auth或Facebook Auth按钮时,它在Activity类中初始化(因为初始化GoogleApiClient我需要Activity上下文,我无法传递给ViewModel,视图模型无法存储Activity字段)。在Activity类中实现了Google Api和Facebook API的所有逻辑:

//google api initialization
googleApiClient = new GoogleApiClient.Builder(this)
                .enableAutoManage(this, this)
                .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
                .build();

//facebook login button
loginButton.setReadPermissions(Arrays.asList("email", "public_profile"));
loginButton.registerCallback(callbackManager,

此外,我需要调用登录意图,这也需要活动上下文:

Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(googleApiClient);
startActivityForResult(signInIntent, GOOGLE_AUTH);

我不能请求facebook登录和google登录,或者从视图模型类请求startActivity intent,所以我创建了类接口AuthActivityListener:

public interface AuthActivityListener {
    void requestSignedIn();

    void requestGoogleAuth();

    void requestFacebookAuth();

    void requestShowDialogFragment(int type);
}

在活动类中实现监听器:

AuthActivityRequester authRequestListener = new AuthActivityRequester() {
        @Override
        public void requestSignedIn() {
            Intent intent = new Intent(AuthActivity.this, ScanActivity.class);
            startActivity(intent);
            AuthActivity.this.finish();
        }

        @Override
        public void requestGoogleAuth() {
            Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(googleApiClient);
            startActivityForResult(signInIntent, GOOGLE_AUTH);
        }
        ...

并在视图模型类中分配此侦听器以调用活动方法:

// in constructor
this.authRequester = listener;

// call activity method
public void onClickedAuthGoogle() {
        authRequester.requestGoogleAuth();
}

在google或facebook认证通过后,我从活动中调用视图模型方法:

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        callbackManager.onActivityResult(requestCode, resultCode, data);
        if (requestCode == GOOGLE_AUTH) {
            GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
            if (result.isSuccess()) {
                GoogleSignInAccount acct = result.getSignInAccount();
                if (acct != null) {
                    viewModel.onGoogleUserLoaded(acct.getEmail(), acct.getId());
                } else {
                    viewModel.onGoogleUserLoaded("", "");
                }
            }
        }
    }

任何人都可以解释一下,视图模型和活动之间的这种沟通方式是对的,还是我需要找到另一种从视图模型中调用活动方法的方法?

android android-activity mvvm listener viewmodel
2个回答
1
投票

MVVM最困难的部分是View模型,必须不了解视图并引用它们

这是一个非常强烈的限制。

你有一些选择

1.查看接收上下文参数的模型方法

您可以使方法从视图中接收上下文(此方法从视图中调用)。

在您可以实例化上下文相关变量之后。

如果您了解内存泄漏,只需在视图暂停时将其销毁或停止使用生命周期感知AAC,并在恢复或启动Activity或Fragment时重新启动。

关于onActivityResult,我认为您的解决方案并不错,因为API支持就是这样。

2.使用数据绑定从视图中获取上下文

在布局xml中,您可以使用事件侦听器发送视图本身。

<Button
    ....
    android:onClick=“@{(view) -> vm.onClickFacebookLogin(view)}”

然后,您可以从Viewmodel中的视图接收视图并检索上下文

3.使用AndroidViewModel

AndroidViewModel类与ViewModel类相同,没有应用程序上下文。

您可以使用应用程序上下文

gerApplication()

谢谢


-1
投票

你的方法很好。但不知何故,你的界面依赖于活动意味着如果你重复使用你的视图这些界面没有用,或者可能是为了那个场景,你必须创建新的界面来解决你的问题。

但是,如果您创建一个Activity实例,那么您可以控制它。

© www.soinside.com 2019 - 2024. All rights reserved.