【问题标题】:Java variable scope - copying bitmaps?Java 变量范围 - 复制位图?
【发布时间】:2015-08-21 21:35:55
【问题描述】:

我试图更好地理解 Java 变量作用域是如何工作的,以及当我们在方法中执行类似以下操作时底层数据究竟会发生什么:

this.variable = variable

这条线到底是做什么的?这是我的实际问题:

我正在加载位图以在我的 (Android) OpenGL ES 2.0 项目中应用为纹理。它是这样的:

public loadBitmapsForTextures(){

    myBitmap = BitmapFactory.decodeResource(view.getResources(), R.drawable.testbmp, Options);

    myObject.setTexture(view, myBitmap);

    Log.v("NewTag","Recycled: Again: "+myBitmap);

    myBitmap.recycle(); //All done - no longer required.  But why is myBitmap still valid here?
}

在我的 Sprite 类(其中 myObject 是一个对象)中,我有以下内容:

public void setTexture(GLSurfaceView view, Bitmap imgTexture){
        
        this.imgTexture=imgTexture;  //What exactly is this line doing?  Copying the actual data?  Just making another 'pointer' to the original data?

        iProgId = Utils.LoadProgram(strVShader, strFShader);
        iBaseMap = GLES20.glGetUniformLocation(iProgId, "u_baseMap");
        iPosition = GLES20.glGetAttribLocation(iProgId, "a_position");
        iTexCoords = GLES20.glGetAttribLocation(iProgId, "a_texCoords");
        //Return usable texture ID from Utils class
        texID = Utils.LoadTexture(view, imgTexture);
                    
        Log.v("NewTag","Recycled: Before: "+imgTexture);
        imgTexture.recycle();
        imgTexture=null;
        Log.v("NewTag","Recycled: After"+imgTexture);           
        
}

setTexture 方法中的日志给出了我期望的结果。第一个为位图命名:

回收:之前:android.graphics.Bitmap@1111111

回收:之后:null

但是,初始 loadBitmapsForTextures() 方法中的日志语句给出了一些我没有预料到的东西:

回收:再次:android.graphics.Bitmap@1111111

为什么允许我(看似)再次回收此位图?我只能假设我对以下行的理解是有缺陷的:

this.imgTexture=imgTexture;

那么,这条线到底做了什么?据我所知,它将类变量应用到与局部变量相同的值(被传递到方法中),但是,显然还有更多事情正在发生。它真的会创建一个全新的位图吗?如果是这样,为什么登录时名称相同?

【问题讨论】:

  • 什么都没有发生。你打电话给recycle 两次。看看你的代码。在setTexture 内部调用imgTexture.recycle();,然后在loadBitmapsForTextures() 内部调用myBitmap.recycle();
  • @Max,是的,我知道,我是故意这样做的,这就是我要问的。如果我在 setTexture() 中回收位图,为什么它在 loadBitmapForTextures() 中仍然有效?干杯。
  • 因为myBitmapimgTexture 是指向同一个对象的两个独立变量。所以,当你说imgTexture = null 这意味着imgTexture 现在什么都没有。不,你在哪里告诉myBitmap 指向任何内容,所以它仍然指向原始纹理。有意义吗?

标签: java bitmap scope recycle


【解决方案1】:

对于简单的布尔值和数值以外的任何东西,都是通过引用传递的。所以

Object o1 = new Object();

创建一个新对象并将名为 o1 的引用分配给内存中的区域。

Object o2 = o1;

将名为 o2 的新引用分配给内存中的同一区域。当你调用带参数的方法时也会发生同样的事情。您正在处理的是同一个实体,而不是副本。

【讨论】:

    【解决方案2】:

    这一行将实例成员imgTexture 设置为引用其引用已传递给方法的同一对象。

    this.imgTexture=imgTexture;   
    

    此行将传递给方法的引用设置为 null,这不会更改 this.imgTexture

    imgTexture=null;
    

    也许您希望将其替换为

    this.imgTexture=null;
    

    如果您希望对象不再包含对该位图的引用。

    【讨论】:

    • 好的@Eran,这是有道理的,但是,我仍然感到困惑。我已经放置(除了 imgTexture.recycle() & imgTexture = null),this.imgTexture.recycle() 和 this.imgTexture = null。现在,当我运行代码时,它仍然允许我从 loadBitmapsForTextures() 进行回收 - 即使记录确认(来自 setTexture())imgTexture 和 this.imgTexture 现在都为空,它仍然具有相同的名称?我错过了什么吗?谢谢
    • @Zippy loadBitmapsForTextures 将位图分配给一个名为 myBitmap 的变量(我不确定该变量是在哪里声明的),所以即使你调用了 setTexturemyBitmap 仍然有一个引用到位图(setTextture 不能将其更改为 null,除非 myBitmap 也是一个实例变量,在这种情况下您可以编写 this.myBitmap = null; 。问题是为什么在同一个位图上调用 recycle() 两次。
    • 好的,所以 myBitmap 在名为 Resources 的类中声明(这是偶然调用 loadBitmapsForTextures 的地方)。显然 loadTexture 方法是从不同的类(在我的例子中是 Sprite)调用的,关于调用回收两次,这只是为了测试,我想确保 setTexture 中的回收调用实际上是回收原始位图,而不是.从 loadBitmapFromTextures 调用回收时,我预计会发生崩溃,因为我希望它已经被回收并为空。
    • @Zippy 你在原始位图上调用recycle 两次。 This will not free the pixel data synchronously; it simply allows it to be garbage collected if there are no other references. The bitmap is marked as "dead", meaning it will throw an exception if getPixels() or setPixels() is called, and will draw nothing。没有说第二次调用recycle 会引发异常。我解释了为什么myBitmap 在调用 setTexture 后不为空。
    • 嗯,好的-知道了@Eran,是的,我确实记得前一段时间在已回收的位图上调用 getPixels() 时遇到问题。谢谢,我明白了。我会再读几遍你的答案,以确保我明白了。
    猜你喜欢
    • 2013-12-28
    • 1970-01-01
    • 1970-01-01
    • 2011-06-01
    • 2011-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-23
    相关资源
    最近更新 更多