【问题标题】:How to pass a Bitmap from an Activity to an other in a fast way?如何以快速的方式将位图从 Activity 传递给另一个?
【发布时间】:2019-02-22 13:28:24
【问题描述】:

我正在尝试将位图从一个 Activity 传递给另一个,我尝试了多种解决方案,但速度不够快。

目前我正面临这个问题:当我单击下一个按钮时,它会冻结 2 秒钟,然后移动到下一个 Activity,ImageView 中显示了正确的位图。

我在 StackoverFlow 中找到了这个解决方案。这是代码:

  Uri imageUri = intent.getParcelableExtra("URI");
        if (imageUri != null) {
            imageView.setImageURI(imageUri);
            try {
                bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageUri);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            Toast.makeText(this, "No image is set to show", Toast.LENGTH_LONG).show();
        }

  btn_next_process.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (bitmap == null) {
                Toast.makeText(CropResultActivity.this, "Emptyyy", Toast.LENGTH_SHORT).show();
            }
            else {
                try {
                    //Write file
                    String filename = "bitmap.png";
                    FileOutputStream stream = CropResultActivity.this.openFileOutput(filename, Context.MODE_PRIVATE);
                    bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);

                    //Cleanup
                    stream.close();
                  //  bitmap.recycle();

                    //Pop intent
                    Intent in1 = new Intent(CropResultActivity.this, InputProcessingActivity.class);
                    in1.putExtra("image_data", filename);
                    startActivity(in1);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    });

然后我尝试先将文件保存在工作线程中,当我单击下一步按钮时我检索它,现在它工作得很快,但我得到一个错误的位图。

代码如下:

  Uri imageUri = intent.getParcelableExtra("URI");
        if (imageUri != null) {
            imageView.setImageURI(imageUri);
            try {
                bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageUri);

                new Thread() {
                    @Override
                    public void run() {
                        try {
                            //Write file
                            FileOutputStream stream = CropResultActivity.this.openFileOutput(filename, Context.MODE_PRIVATE);
                            bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
                            //Cleanup
                            stream.close();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }.run();

            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            Toast.makeText(this, "No image is set to show", Toast.LENGTH_LONG).show();
        }

  btn_next_process.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (bitmap == null) {
                Toast.makeText(CropResultActivity.this, "Empty", Toast.LENGTH_SHORT).show();
            }
            else {
                //Pop intent
                Intent in1 = new Intent(CropResultActivity.this, InputProcessingActivity.class);
                in1.putExtra("image_data", filename);
                startActivity(in1);
            }
        }
    });

在第二个活动中,我以这种方式检索位图:

  private void getIncomingIntent(){
    if(getIntent().hasExtra("image_data")){
        try {
            String filename = getIntent().getStringExtra("image_data");
            FileInputStream is = this.openFileInput(filename);
            imageToProcess = BitmapFactory.decodeStream(is);
            process_detect_edges(imageToProcess);
            is.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

我做错了什么?

【问题讨论】:

  • 位图也是 Parcelable 的。为什么不直接通过 Intent 传递呢?
  • 我已经读过,如果你有意传递洞位图,随着尺寸的增加,你会得到“java.lang.SecurityException”,这不是最佳实践。

标签: java android android-intent android-activity bitmap


【解决方案1】:

只需将图像 uri 传递给下一个活动。在其他活动中从 uri 加载。

【讨论】:

  • 我会尝试您的解决方案并及时更新。谢谢。
  • 当然。乐于助人。
  • 很抱歉发布了一段不完整的代码,但我没有从 Uri 设置图像,实际上这是一个 if else 语句。所以我尝试在第一个 Activity 中转换位图到 byteArray,我有一个 TransactionTooLargeException。然后我尝试在第二个 Activity 中使用静态变量,现在它就像一个魅力。请原谅我的长时间更新。
【解决方案2】:
  1. 创建一个普通的Service。给 Service 一个 public Bitmap mBitmap 成员。
  2. 将每个Activity 绑定到Service,而它们在onStart()onStop() 之间。
  3. 如果您的Activities 引用了Service,他们可以直接通过mBitmap 成员进行通信。一个Activity 可以设置mBitmap,然后启动另一个Activity。第二个Activity 可以简单地获取引用(当然是在绑定之后),然后开始操作Bitmap。由于一切都发生在 UI 线程上,因此没有同步问题。而且一切都很快。

这个方案没有解决持久化问题:如果用户离开应用一段时间(置后台,锁屏等),那么整个应用可能会被销毁,mBitmap会迷失。但是,如果您只是想在两个连续的Activities 之间共享数据,这是一种直接的方式。

您甚至可以通过public static 引用分享Bitmap,放在任何方便的类中。有传言说垃圾收集器会随心所欲地将static 引用设置为null,但这是对实际行为的误解:整个应用程序可能会在意外的时间被清理掉。当您返回 Activity 时,系统实际上可能必须重新启动应用程序并从头开始重新创建 Activity。在这种情况下,引用将被重置为null

相反,使用Service 向操作系统表明您的应用程序组件的寿命应该更长一些。当然,它将继续存在于两个连续的Activities 之间。

请注意,在 Oreo 及更高版本上,系统会在应用程序离开前台后立即清理它们。

【讨论】:

  • 我非常感谢您的解决方案,我认为它是正确使用的解决方案。您如何看待使用枚举?
  • 枚举?你失去了我。
  • 抱歉造成误解,我的意思是使用带有静态方法的枚举在我的目标 Avtivity 中设置和获取位图。我认为使用枚举将消除使用单例引用的需要,并且引用总是在我的活动收到后被删除。
  • 我并不反对使用静态引用,但我看不出枚举会​​有什么用处,甚至是相关的。你能再解释一下吗?
  • Enum 是值类型变量,所以当 Activity 找不到任何其他对它的引用时,它会自动释放。这样我就不用担心在使用后释放我的静态变量了。
猜你喜欢
  • 1970-01-01
  • 2018-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-08
  • 2020-10-19
  • 1970-01-01
相关资源
最近更新 更多