【问题标题】:How to use a ViewModel to save a bitmap correctly?如何使用 ViewModel 正确保存位图?
【发布时间】:2020-04-09 02:38:26
【问题描述】:

official android documentation中,关于如何实现ViewModel有这个方法:

private void loadUsers() {
        // Do an asynchronous operation to fetch users.
    }

在我的情况下,我不需要获取任何数据,我只想将 bitmap 保存在 ActivityClass 之外的另一个类中。

我尝试创建一个 setter 方法,但我无法创建 ViewModel 类的对象!

  • 这是我的 ViewModel 类:

    public class MyViewModel extends ViewModel {
    
      private MutableLiveData<Bitmap> bitmapMutableLiveData;
    
      public LiveData<Bitmap> getBitmapMutableLiveData() {
        if (bitmapMutableLiveData == null) {
            bitmapMutableLiveData = new MutableLiveData<Bitmap>();
        }
        return bitmapMutableLiveData;
      }
    
      public void setBitmap(Bitmap bitmapImage) {
        bitmapMutableLiveData.postValue(bitmapImage);
      }
    }
    
  • 这是我获取和设置位图的地方:

       void loadScaledImage(Uri photoUri){
    
        mUpdateGraphicViews.onClear();
    
        if(photoUri != null){
            bitmapImage = decodeSampledBitmapFromUri(photoUri);
    
            mImageView.setImageBitmap(bitmapImage);
            mFTR.recognizeTextFromImage(getScaledBitmap(bitmapImage));
        }
    }
    

那么,如何使用ViewModel 以正确的方式保存bitmap?谢谢!


编辑:

我犯了一个错误,将 ViewModel 类放在包之外,但我修复了这个问题,并在前面提到的 loadScaledImage() 方法中调用了类似的 setter 方法。

myViewModel.setBitmap(bitmapImage);

但是,现在我在onCreate() 方法中遇到了一个新问题!!!

MyViewModel model = new ViewModelProvider(this).get(MyViewModel.class); //Cannot resolve constructor ViewModelProvider(com.ziad.sayit.PreviewActivity)
        model.getBitmapMutableLiveData().observe(this, bitmapMutableLiveData -> { //Lambda expressions are not supported at language level 7
            // update UI
        });

我注意到ViewModelProvider() 构造函数在super-class 中接受了两个参数,但现在文档中就是这种情况,第二个很奇怪,我有java 8 还是不是这样?


更新:

使用我找到的这两个答案,我能够解决我的最后一个问题:

Cannot resolve ViewModelProvider construction in a fragment?

Java "lambda expressions not supported at this language level"

  • 那么,现在,这就是我设置和获取位图的方式:

ViewModel 对象作为全局变量:

Bitmap savedImage;
MyViewModel model;

这是onCreate():

model = new ViewModelProvider(this).get(MyViewModel.class); 
        model.getBitmapMutableLiveData().observe(this, bitmapMutableLiveData -> { 

            savedImage = bitmapMutableLiveData;
        });

然后我就是这样设置bitmap

if(savedImage != null) {
    helper.loadSavedBitmap(savedImage); //load the saved image
}else{
    helper.loadScaledImage(imageUri);   //there is a bunch of code before this but I delete it for the simplicity
    model.setBitmap(helper.bitmapImage); //set that new Image
}

但后来我测试了应用程序,没有任何改变!


更新 2:

所以,我发现ViewModel 不像普通代码那样工作。 上面代码中的问题是我在使用它时忽略了ViewModel 的生命周期及其条款(因为我什么都不知道),但我注意到了(如果我说错了,请纠正我):

  1. ViewModel 不按代码顺序运行,但是,它 在onCreate() 中的所有内容之后运行。这就是为什么你不能依赖 像我一样将值保存到全局变量中。
  2. 如果ViewModel 上没有存储任何值,它在 全部!因此,无需检查其中是否有值。
  3. 每次调用onResume()onStart() 时都会调用它-I'm 不太确定是哪一个——不管onCreate() 是 是否被调用..

所以,我重构了代码,但仍然,我缺少一些东西!即使ViewModel,所有代码都可以正常工作,但是当我更改设备语言检查是否成功使用保存的图像..出现错误!

我正在与您分享我的代码:

PreviewActivity(我使用ViewModel

Helper class(准备图片并设置到屏幕上)

MainActivity(启动 PreviewActivity)

LogCat Error

【问题讨论】:

    标签: android bitmap android-architecture-components android-viewmodel android-savedstate


    【解决方案1】:

    您根本无法在任何其他简单的 java 类而不是 Activity 类中创建 ViewModel 对象,因为它的唯一目的是了解 Activity 生命周期。

    虽然我建议不要直接从您的简单 java 类中存储位图,而是在初始化您的viewModel 的活动类中获取您的简单 java 类的实例,从那里您可以将您的位图存储在 viewModel 中。

    【讨论】:

    • 我更新了问题中的一些内容,你能检查一下吗?另外,关于第二部分,您的意思是在SimpleJavaClass 中获取Bitmap 的引用并将其传递给Activity 中的ViewModel
    • 是的,我的意思是,以某种方式在您的活动中获取位图,然后将其存储在 viewModel 中,以便您进行编辑,您的代码看起来不错。你能打印 logcat 吗?
    • 我用我所做的所有新细节更新了我的问题;我没有收到任何错误,但 ModelView 不起作用!!
    • 你好@ZiadH。如果您在此处发布整个活动代码会更好。它将帮助我们查看问题出在哪里。
    • 你好@Parth,抱歉迟到了!我用所有必要的代码和 logcat 以及我迄今为止所做的一切更新了这个问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-20
    • 2019-02-11
    • 2017-01-01
    • 1970-01-01
    • 2012-09-02
    • 1970-01-01
    • 2020-09-09
    相关资源
    最近更新 更多