【问题标题】:Android MVVM - How to get an element from the XML to manipulate it and WhereAndroid MVVM - 如何从 XML 中获取元素来操作它以及在哪里
【发布时间】:2021-10-10 17:57:40
【问题描述】:

我以前在没有任何架构的情况下以传统方式为 android 编程, 但我正在尝试学习如何在 android 中使用 MVVM 架构进行编程。

他们给了我一个架构“准备好”开始的项目,但我需要一点时间才能理解。

我了解在 ViewModel 层中 LiveData 和 MutableLiveData 的使用,以及从 xml 布局访问它以操作元素的目的。 但是,我怎样才能访问这些元素来做一些事情,比如给它们一个动画?。

示例:IDLEMENT.loadAnimation(getApplication(), R.anim.top_animation);

我应该将 LoginBindingactivity 从 View 层 (LoginActivity) 发送到 ViewModelLayer(LoginViewModel) 吗?

像这样:loginViewModel.loginAnimation(activityLoginBinding) ? , 然后在 ViewModel 中执行此操作:activityLoginBinding.backgroundLayout.setAnimation(topAnim);?

XML

<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<data>
    <variable
        name="model"
        type="com.qsafeguardiaseguridad.viewmodel.LoginViewModel" />
</data>
<ImageView
    android:id="@+id/backgroundLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_weight="4"
    android:scaleType="centerCrop"
    android:src="@drawable/ic_login" />
</layout>

查看(登录活动)

public class LoginActivity extends AppCompatActivity {

//1) Inicio flujo en Activity
private LoginViewModel loginViewModel = null;
private ActivityLoginBinding activityLoginBinding = null;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    
    activityLoginBinding = DataBindingUtil.setContentView(this, R.layout.activity_login);
    loginViewModel = new ViewModelProvider(this).get(LoginViewModel.class);
    activityLoginBinding.setModel(loginViewModel);

    loginViewModel.loginAnimation( activityLoginBinding); //should i do this?
}
}

ViewModel (LoginViewModel)

public class LoginViewModel extends AndroidViewModel {

public LoginViewModel(Application application) {
    super(application);
}

public LiveData<String> getUserLiveData(){
    return _userLiveData;
}
private final MutableLiveData<String> _userLiveData = new MutableLiveData<>();

private final MutableLiveData<String> _passwordLiveData = new MutableLiveData<>();
public LiveData<String> getPasswordLiveData(){
    return _passwordLiveData;
}

//variables animacion
Animation topAnim, bottomAnim;

/*Aquí también se manejan los eventos del Activity, en este caso
* un onclick del botón del inicio de sesión*/
public void loginButtonClicked(String user, String password){
    if(!user.isEmpty() && !password.isEmpty()){
        Log.w("Test",user+" "+password);
        LoginRepository.getToken(user, password, getApplication());

    }
}


//Should i do this?
public void loginAnimation(ActivityLoginBinding activityLoginBinding){
    //Animations
    topAnim = AnimationUtils.loadAnimation(getApplication(), R.anim.top_animation);
    bottomAnim = AnimationUtils.loadAnimation(getApplication(), R.anim.bottom_animation);
    activityLoginBinding.backgroundLayout.setAnimation(topAnim);
    activityLoginBinding.formLayout.setAnimation(topAnim);
    activityLoginBinding.versionName.setAnimation(bottomAnim);
}
}

我这样做是对还是错?


更新 #1

尝试应用 King 的建议,这样的事情应该正确吗?

查看(登录活动)

public class LoginActivity extends AppCompatActivity {

//1) Inicio flujo en Activity
private LoginViewModel loginViewModel = null;
private ActivityLoginBinding activityLoginBinding = null;

//variables animacion
Animation topAnim, bottomAnim;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    
    activityLoginBinding = DataBindingUtil.setContentView(this, R.layout.activity_login);
    loginViewModel = new ViewModelProvider(this).get(LoginViewModel.class);
    activityLoginBinding.setModel(loginViewModel);

    topAnim = AnimationUtils.loadAnimation(getApplication(), R.anim.top_animation);
    bottomAnim = AnimationUtils.loadAnimation(getApplication(), R.anim.bottom_animation);
    activityLoginBinding.backgroundLayout.setAnimation(topAnim);
    activityLoginBinding.formLayout.setAnimation(topAnim);
    activityLoginBinding.versionName.setAnimation(bottomAnim);
}

【问题讨论】:

    标签: java android mvvm binding architecture


    【解决方案1】:

    不,不要从 ViewModel 中引用 View; ViewModel 具有生命周期意识。 ViewModel 在 Activity 的整个生命周期中保持其状态,但必须避免对 ViewModel 中的 View 或 Activity 的任何引用,因为这些(视图)在销毁时会引发 NullPointerException。这最终会导致内存泄漏。

    动画应该在then view层进行,Activity和Fragments都是Views

    1. 你可以在主Activity中做动画

    2. 在单独的片段中制作动画,即 loginFragment

    【讨论】:

    • 谢谢!,你能给我关于我的第一次更新的反馈吗?
    • 这在视图中是可以的,但更简洁的方法是导航到一个片段,该片段执行动画,然后一旦它完成,它将导航到您的初始活动。在 MVVM 中,您希望您的活动专注于处理生命周期事件。
    猜你喜欢
    • 2013-08-09
    • 2013-07-07
    • 2017-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多