-1

I had the question:

Why is this not working sometimes?

I was comparing bitmaps and executing code accordingly, but the code wasn't executing. My question received many great answers. One of the answers, which worked, suggested to remove ==, and change it to .sameAs() in order to make my app work on newer phones.

ClickGround = v.getBackground(); //Get the background of button clicked (ClickGround is a bitmap)
        BitClick = ((BitmapDrawable) ClickGround).getBitmap(); //the bitmap background of the button clicked

So, why does using the sameAs() method work more efficiently than using == to compare bitmaps? Also, why does using == work in lower versions of android (kitkat), and sameAs in higher versions?

Thanks,

Ruchir

Community
  • 1
  • 1
Ruchir Baronia
  • 7,406
  • 5
  • 48
  • 83
  • If you notice in the linked question, you will see the first answer states something about how "I am comparing different objects". Why? – Ruchir Baronia Jan 22 '16 at 03:04

3 Answers3

0

Just to be clear, sameAs() doesn't work "more efficiently", but rather it is the only one that works correctly/reliably. That's because == only decides if two objects are identical - i.e., point to the same object - but may return false even for bitmaps that are exactly the same, but happen to be different objects.

The methods you are calling may, on certain devices and within the contract of the API, return different objects for the same bitmap, so == will return false. sameAs() will return true if the bitmap is the same (as in identical in all properties):

Given another bitmap, return true if it has the same dimensions, config,
and pixel data as this bitmap. If any of those differ, return false. If 
other is null, return false. 

It's the same idea behind:

void foo(Integer a, Integer b) {
  if (a == b) {
   ...
  }
}

That's almost certainly wrong - you usually want a.equals(b) or perhaps Objects.equals(a, b) if a can be null, since otherwise even calls like:

foo(1234, 1234)

will often fail the comparison above.

BeeOnRope
  • 60,350
  • 16
  • 207
  • 386
  • So it only works when the objects are of the same class? – Ruchir Baronia Jan 22 '16 at 03:17
  • No. That is, I'm not sure what you mean by "it works", but it isn't really related to class. A good rule of thumb is that at least until you understand this well you should _almost never_ use `==` to compare objects. You almost always use `equals` or another comparable method to determine if the objects are the same. In the case of Bitmap, that method is `sameAs(). – BeeOnRope Jan 22 '16 at 03:20
  • Okay, let me rephrase my question. How would you define, "Two objects being identical"? – Ruchir Baronia Jan 22 '16 at 03:23
  • In the specific context of the java language specification, identical for object references mean the references point at the same object. For example, in the snippet: `Integer a = new Integer(1), b = a;`, `a` and `b` are identical and `a == b` because they both point at the same object. However, in the case: `Integer a = new Integer(1), b = new Integer(1);`, they are *not* identical, and `a != b`. Both `a` and `b` have value 1, so they are the "same" or "equal", but not identical (formally speaking) since they point to different objects. – BeeOnRope Jan 22 '16 at 03:28
0

== is a relational operator and thus is really only good for numeric representative values

However, sameAs() is looking at the DATA that is contained and not the whole file and everything about it.

For instance:

int a = 3; 
String b = "3"; 

We know that 3 is a numeric value and "3" is a String representing a numeric value. They both represent the same thing to a normal person, but a computer. In this case, if you tried to compare

if (a==b){//something}

We know that we have to do some kind of translation since the two are not the same to a computer.

Something like

if (Integer.parseInt("b") == a){//do something}

would be needed or even

if( Integer.toString(a).equals(b)){//do something)

In the case of images, the two have totally different locations and other reference, so they could never be "equivalent" for a == type comparison. Even with both as strings, they have different places which they are held in memory and different associative values which is why .equals() is used.

In the case of Bitmaps, they are an abstract data type so even equals() would not apply here. Because you need to compare the abstract data contained sameAs()is used.

childofthehorn
  • 697
  • 1
  • 4
  • 12
  • Then when should I use `equals()` over `sameAs()`? – Ruchir Baronia Jan 22 '16 at 03:24
  • It depends on the class in question. The best practice is that _value objects_ override `equals` to allow for a more meaningful equality comparison (otherwise it defaults to identity which is the same as `==` as I described in my answer). For whatever reason, the Android `Bitmap` class does not override `equals()` but instead defines `sameAs()` with essentially the same purpose. I'm not sure why, but you could always start a new question for that. – BeeOnRope Jan 22 '16 at 03:34
  • Well remember that Android has some interesting things around bitmaps, take the MediaStore API for instance. The sameAs() would not be the same return "values" as equals in that case. It has to actually "look" at the bitmap and use the sameAs comparison since they are an abstract data type and equals would not apply in those cases. The example was really to make it understood in a human way. – childofthehorn Jan 22 '16 at 03:39
0

So, why does using the sameAs() method work more efficiently than using == to compare bitmaps?

It doesn't work more efficiently. When == works, it is more efficient than sameAs().

However, sameAs() works in situations where == does not work. That is the reason you should use sameAs() rather than == to compare bitmaps.

Also, why does using == work in lower versions of android (kitkat), and sameAs in higher versions?

Something about the way that the Bitmap objects are being created and shared (or not) has changed in newer versions. When you were testing using ==, you were relying on a undocumented implementation specific behavior. That behavior has changed.

Why has it changed? My guess is that it is a side-effect of a change to a behind-the-scenes bitmap caching mechanism.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216