在Android中使用Intent在活动中传递android位图数据


74

我有一个bmp在Activity1中命名的Bitmap变量,我想将该位图发送到Activity2

以下是我用于传递意图的代码。

Intent in1 = new Intent(this, Activity2.class);
in1.putExtra("image",bmp);
startActivity(in1);

在Activity2中,我尝试使用以下代码访问位图

Bundle ex = getIntent().getExtras();
Bitmap bmp2 = ex.getParceable("image");
ImageView result = (ImageView)findViewById(R.Id.imageView1);
result.setImageBitmap(bmp);

该应用程序无一例外地运行,但是没有给出预期的结果


3
这不是您的代码的副本,因为我看到至少有两个错字。
克里斯汀(Christine)

@Christine:这确实是我的代码,但是,但是我从许多教程中得到了它……XP
adi.zean 2012年

2
那么,如何创建一个位图bmp2,并使用setImageBitmap(bmp)进行设置?当然,R.Id.imageView1不起作用。它应该是R.id.imageView1。
克里斯汀(Christine)

3
您当然可以将位图写入文件,然后在第二个活动中读取该文件。如果设备旋转,则可以使用相同的文件来确保保留图像。
克里斯汀(Christine)

1
发帖提问之前,请确保你理解你的代码的发布,从StackOverflow上一个普通的复制粘贴到修复bug也没用.. @Christine -我正要点评一下错别字..同样的事情
milosmns

Answers:


206

在将其添加到意图,将其发送和解码之前,将其转换为Byte数组。

//Convert to byte array
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();

Intent in1 = new Intent(this, Activity2.class);
in1.putExtra("image",byteArray);

然后在活动2中:

byte[] byteArray = getIntent().getByteArrayExtra("image");
Bitmap bmp = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.length);

编辑

我认为我应该以最佳做法来对此进行更新:

在第一个活动中,应将位图保存到磁盘,然后在下一个活动中将其加载。确保在第一个活动中回收您的位图,以便对其进行垃圾回收:

活动1:

try {
    //Write file
    String filename = "bitmap.png";
    FileOutputStream stream = this.openFileOutput(filename, Context.MODE_PRIVATE);
    bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);

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

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

在活动2中,加载位图:

Bitmap bmp = null;
String filename = getIntent().getStringExtra("image");
try {
    FileInputStream is = this.openFileInput(filename);
    bmp = BitmapFactory.decodeStream(is);
    is.close();
} catch (Exception e) {
    e.printStackTrace();
}

干杯!


7
这解决了我遇到的一个问题。由于“ transactionTooLargeException”而引发了异常。当发送额外的完整位图时。
2013年

更好的解决办法是在这里stackoverflow.com/questions/2459524/...
Nizzy

只是想知道如何在片段中使用getIntent()?我读过这是不可能的,但是必须有一种方法。
StillLearningToCode 2014年

1
bytearray =内存中有3张图像(第一位,bmp数组,bmp第二位)文件=内存中有2张图像(第一位,bmp,第三位bmp文件)
Zaid Daghestani 2015年

1
我强烈建议您避免使用字节数组,因为您可能会达到2MB的限制并出现泄漏。我建议创建一个临时文件并处理其通过活动的路径
Trinity

11

有时,位图可能太大,无法进行编码和解码,或者可能作为意图中的字节数组传递。这可能会导致OOM或不良的UI体验。

我建议考虑将位图放入新活动(使用它的活动)的静态变量中,当您不再需要它时(该值在onDestroy中,但仅当“ isChangingConfigurations”返回false时)才小心地为null。


3

简单地说,我们只能传递位图的Uri而不传递位图对象。如果Bitmap对象为Big,则将导致内存问题。

FirstActivity。

intent.putExtra("uri", Uri);

从SecondActivity我们返回位图。

Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(),Uri.parse(uri));

当我通过uri中的图像路径时出现IOexception。可能是什么原因。
Dilip Poudel

1

Kotlin代码,用于通过意图将位图发送到另一个活动:

第一活动中的1:

          val i = Intent(this@Act1, Act2::class.java)
           var bStream  =  ByteArrayOutputStream()
            bitmap.compress(Bitmap.CompressFormat.PNG, 50, bStream)
            val byteArray = bStream.toByteArray()
            i.putExtra("image", byteArray )
            startActivity(i)

2-在活动二中(读取位图图像):

 var bitmap : Bitmap? =null
    if (intent.hasExtra("image")){
      //convert to bitmap          
        val byteArray = intent.getByteArrayExtra("image")
        bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.size)
    }

3-如果需要将其设置为视图的背景,例如ConstraintLayout或...:

 if (bitmap != null) {
     //Convert bitmap to BitmapDrawable
     var bitmapDrawable = BitmapDrawable( resources , bitmap)
      root_constraintLayout.backgroundDrawable = bitmapDrawable
   }

Google刚刚宣布由于缺乏用户适应性而停止了Kotlin的开发
-CaptainCrunch

0

我们也可以解决此问题,而无需通过意图传递数据。只需将图像存储在内存中,然后在下一个活动中仅从该位置加载图像即可,这还可以避免应用程序崩溃传递大量位图数据。注意:您甚至无需将位置路径传递给意图,记住路径并使用它。


0

我也想为那些希望这样做的人发布最佳实践答案(但可能会问错问题)。

建议不要使用位图(我想您是从网络上下载的,否则,您已经有文件引用了),我建议使用图像加载器(例如Universal Image Loader)将图像下载到ImageView中。您可以配置它,然后将映像缓存到磁盘:

 DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()
                .cacheInMemory(true)
                .cacheOnDisk(true)
                .considerExifParams(true)
                .bitmapConfig(Bitmap.Config.RGB_565)
                .build();
        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
                .defaultDisplayImageOptions(defaultOptions)
                .build();

        ImageLoader.getInstance().init(config);

现在,只需按意图传递图像URL,然后使用UIL加载图像。例如,在您新创建的活动中,图像将立即加载,因为它是从缓存中加载的-即使您的图像URL自下载以来已过期。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.