如何在 ViewModel 中保存图像以处理方向变化?
How to save image inside ViewModel to handle orientation change?
我的 activity 包含一个图像视图和一个按钮,当单击按钮时,图像视图中的图像被更改(工作正常)。
但是当屏幕方向改变时,imageview 中的图像丢失(因为 activity 被重新创建)。
我在一些 post 中读到,与 onSaveInstanceState 相比,ViewModel 可以保存方向并且可以存储大量数据(位图)。
还有很多其他选项可以检索同一张图片,但我想使用 ViewModel 来获取同一张图片而不受方向变化的影响。
那么,如何使用 ViewModel 获得相同的图像?
谢谢。
您的 ViewModel 应该有一个方法 changeImage
可以更改 ViewModel 的内部状态。您必须以某种方式指明 activity 有关此更改。为此,最好使用 val imageId = MutableLiveData<Int>()
.
changeImage
更改此值。在 Activity 中,您可以订阅更改并在 imageId 更改时应用新图像。
使用 ViewModel 处理 TextView 和 ImageView 以适应方向变化的简单示例
例子解释:
Layout 包含一个TextView、ImageView 和一个Button。最初,文本和图像设置在布局中的 TextView 和 ImageView 上。单击按钮时,文本(以编程方式)和图像(来自可绘制对象)设置为适当的视图。
假设设备旋转,因此在单击按钮时设置的文本和图像由于activity 重新创建而丢失,因此加载在xml 文件中设置的文本和图像。
为了解决这个问题,我们使用 ViewModel 来处理配置更改。
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:id="@+id/my_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Android" />
<ImageView
android:id="@+id/my_image"
android:layout_width="96dp"
android:layout_height="96dp"
android:layout_margin="20dp"
android:src="@drawable/ic_android_black_24dp" />
<Button
android:id="@+id/my_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:text="Update text and image" />
</LinearLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
TextView mText;
ImageView mImageView;
Button mButton;
MyViewModel mViewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mText = findViewById(R.id.my_text);
mImageView = findViewById(R.id.my_image);
mButton = findViewById(R.id.my_button);
mViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
if (mViewModel.getText() != null) {
mText.setText(mViewModel.getText());
}
if (mViewModel.getImage() != null) {
mImageView.setImageDrawable(mViewModel.getImage());
}
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mText.setText("Happy Coding...");
mImageView.setImageDrawable(getResources().getDrawable(R.drawable.ic_face));
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
mViewModel.setText(mText.getText().toString());
mViewModel.setImage(mImageView.getDrawable());
}
}
MyViewModel.java
public class MyViewModel extends ViewModel {
private String text;
private Drawable image;
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Drawable getImage() {
return image;
}
public void setImage(Drawable image) {
this.image = image;
}
}
关于 ViewModel 的几个小技巧:
- ViewModel class 旨在以 life-cycle 有意识的方式保存和管理 UI-related 数据。这允许数据在配置更改(例如屏幕旋转)后继续存在。
- ViewModel 将 UI 实现与您应用的数据分开。 ViewModel 的生命周期从关联的 UI 控制器首次创建时开始,直到它被完全销毁。
- 切勿将 UI 控制器或上下文直接或间接存储在 ViewModel 中。这包括将 View 存储在 ViewModel 中。直接或间接引用 UI 控制器会破坏将 UI 与数据分离的目的,并可能导致内存泄漏。
- ViewModel 还可以很好地与另一个架构组件(如 LiveData、Room)配合使用。使用 LiveData 的额外好处是它是可观察的:它可以在数据更改时触发 UI 更新。使用以下链接了解更多信息。
链接:
https://developer.android.com/topic/libraries/architecture/viewmodel
https://developer.android.com/topic/libraries/architecture/livedata.html
代码实验室链接:
https://codelabs.developers.google.com/codelabs/android-room-with-a-view/#0
我不是专业开发人员。上面的代码对我有用。欢迎指正或建议。
谢谢 ;)
我的 activity 包含一个图像视图和一个按钮,当单击按钮时,图像视图中的图像被更改(工作正常)。
但是当屏幕方向改变时,imageview 中的图像丢失(因为 activity 被重新创建)。
我在一些 post 中读到,与 onSaveInstanceState 相比,ViewModel 可以保存方向并且可以存储大量数据(位图)。
还有很多其他选项可以检索同一张图片,但我想使用 ViewModel 来获取同一张图片而不受方向变化的影响。
那么,如何使用 ViewModel 获得相同的图像?
谢谢。
您的 ViewModel 应该有一个方法 changeImage
可以更改 ViewModel 的内部状态。您必须以某种方式指明 activity 有关此更改。为此,最好使用 val imageId = MutableLiveData<Int>()
.
changeImage
更改此值。在 Activity 中,您可以订阅更改并在 imageId 更改时应用新图像。
使用 ViewModel 处理 TextView 和 ImageView 以适应方向变化的简单示例
例子解释:
Layout 包含一个TextView、ImageView 和一个Button。最初,文本和图像设置在布局中的 TextView 和 ImageView 上。单击按钮时,文本(以编程方式)和图像(来自可绘制对象)设置为适当的视图。
假设设备旋转,因此在单击按钮时设置的文本和图像由于activity 重新创建而丢失,因此加载在xml 文件中设置的文本和图像。
为了解决这个问题,我们使用 ViewModel 来处理配置更改。
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
tools:context=".MainActivity">
<TextView
android:id="@+id/my_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Android" />
<ImageView
android:id="@+id/my_image"
android:layout_width="96dp"
android:layout_height="96dp"
android:layout_margin="20dp"
android:src="@drawable/ic_android_black_24dp" />
<Button
android:id="@+id/my_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:text="Update text and image" />
</LinearLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
TextView mText;
ImageView mImageView;
Button mButton;
MyViewModel mViewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mText = findViewById(R.id.my_text);
mImageView = findViewById(R.id.my_image);
mButton = findViewById(R.id.my_button);
mViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
if (mViewModel.getText() != null) {
mText.setText(mViewModel.getText());
}
if (mViewModel.getImage() != null) {
mImageView.setImageDrawable(mViewModel.getImage());
}
mButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mText.setText("Happy Coding...");
mImageView.setImageDrawable(getResources().getDrawable(R.drawable.ic_face));
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
mViewModel.setText(mText.getText().toString());
mViewModel.setImage(mImageView.getDrawable());
}
}
MyViewModel.java
public class MyViewModel extends ViewModel {
private String text;
private Drawable image;
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Drawable getImage() {
return image;
}
public void setImage(Drawable image) {
this.image = image;
}
}
关于 ViewModel 的几个小技巧:
- ViewModel class 旨在以 life-cycle 有意识的方式保存和管理 UI-related 数据。这允许数据在配置更改(例如屏幕旋转)后继续存在。
- ViewModel 将 UI 实现与您应用的数据分开。 ViewModel 的生命周期从关联的 UI 控制器首次创建时开始,直到它被完全销毁。
- 切勿将 UI 控制器或上下文直接或间接存储在 ViewModel 中。这包括将 View 存储在 ViewModel 中。直接或间接引用 UI 控制器会破坏将 UI 与数据分离的目的,并可能导致内存泄漏。
- ViewModel 还可以很好地与另一个架构组件(如 LiveData、Room)配合使用。使用 LiveData 的额外好处是它是可观察的:它可以在数据更改时触发 UI 更新。使用以下链接了解更多信息。
链接: https://developer.android.com/topic/libraries/architecture/viewmodel
https://developer.android.com/topic/libraries/architecture/livedata.html
代码实验室链接: https://codelabs.developers.google.com/codelabs/android-room-with-a-view/#0
我不是专业开发人员。上面的代码对我有用。欢迎指正或建议。
谢谢 ;)