• After 15+ years, we've made a big change: Android Forums is now Early Bird Club. Learn more here.

Apps Weird Issue Using onSharedPreferenceChanged()

I'm using Shared Preferences to access user settings and the onSharedPreferenceChanged function to handle changes that need to be made in my app as preferences are changed. It resides in my Preferences class (which implements OnSharedPreferenceChangeListener). I ran into a very weird issue with this function though.

For some reason, if statements don't seem to run inside the function!!! For example, the first line of code in the function below properly displays a toast message that simply says "myKey" with no spaces before or after it. The second line of code should compare the key passed to the function against "myKey" (which results as true) and run the corresponding toast message. However, this never happens!!! I really need to run if statements in here.

Code:
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)
{
    Toast.makeText(this, key, 2000).show(); // displays "myKey" (without quotes)
    if (key == "myKey") {Toast.makeText(this, "It Worked!!!", 2000).show();}  //does nothing!!!
}

I've been staring at this piece of code all night, maybe I'm missing something simple and need a fresh set of eyes. Anyone have any idea why this would happen?

UPDATE:
Upon further testing I found that the following works:

Code:
 if ([B][COLOR="Red"]key == key[/COLOR][/B]) {Toast.makeText(this, "It Worked!!!", 2000).show();}

Which tells me that if statements themselves are working, but it isn't equating key to be equal to "myKey" as it should. Any ideas would be greatly appreciated!!!
 
when you use == I think you just are checking to see if they are both the exact same object reference (or something similar, I forget exactly)


hope that helps!

:)

That is correct. the == operator compares the two operands by reference, that is, it compares the memory location of the two operands. In some cases, such as comparing primitives or comparing View objects that were clicked, this is acceptable, but it is hardly ever acceptible for strings. The .equals() method compares the two items by value, that is, it compares the actual value of the two items being compared--ideal for strings.
 
Upvote 0
you can compare against null with == for strings and objects

And I think you can use it for ints and other numbers and I think other primitives like a char

Anything that descends from object though would need .equals();


Jon can probably explain it better I have such a cold right now my head is gonna asplode. I also know enough java to know what I should be doing not a ton about why it's that way :)
 
Upvote 0
you can compare against null with == for strings and objects

And I think you can use it for ints and other numbers and I think other primitives like a char

Anything that descends from object though would need .equals();


Jon can probably explain it better I have such a cold right now my head is gonna asplode. I also know enough java to know what I should be doing not a ton about why it's that way :)


That is partially correct. Let me try to explain in greater detail.

In Java, everything that is NOT a primitive is a pointer. This includes arrays and objects. I will get to arrays shortly, but for right now, let's focus on primitives and objects.

Say we have the following:
Code:
int numDogs;
Animal dog;

In our example, int is a primitive, and Animal is a pointer. If we tried to do the following:
Code:
numDogs = 8;
if(numDogs == 8)
   Toast.makeText(this, "Blah...", Toast.LENGTH_LONG).show();

it would coimpile and, when run, it would display "Blah..." in a toast message.

This is because, since numDogs is an int and ints are primitives, it compares the VALUE of numDogs with the VALUE of w/e is listed as the trailing operand.

Now say we have the following:

Code:
int numDogs;
String dogName;
dogName = "Henry";
numDogs = 8;

First off, notice that I directly assigned "Henry" to dogName, without using a constructor. This is because when defining text with '"', you are actually creating a new instance of a string. In all actuality, if you do decide to use the String constructor, you are wasting instruction (and performance) by creating an instance of a string with the constructor, creating a second instance with the "" and then copying the second instance's memory location to the first instance's. (I know that is hard to understand.)

Moving on, if you had the following:
Code:
if(dogName == "Henry")
   Log.v("TAG","HENRY!!!");

you'll quickly realize that, no matter what is assigned to dogName, this will always return false (and thus, the Log message will NOT be displayed). This is because dogName and "Henry" are both pointers. When comparing two pointers, you are comparing the location in memory that the two pointers reside at. This will NEVER be the same in this situation, since dogName was declared and allocated at the top of the code, while "Henry" was just now declared and allocated. (There are actually two instances of "Henry" at two different memory locations).

Now, there are some situations where you will actually want to use '==' with objects. Look at this example:

Code:
Button b = (Button)findViewById(R.id.MyButton);
 
void onClick(View v)
{
    if(b == v)
       Log.v("TAG", "Button clicked!");
  }

Here, you are comparing the memory location of b to the memory location of the View that received the click event, v, to make sure that they are the same object. This is a situtation where using '==' on objects is desired.

Lastly, let's take a look at arrays.

Unlike their C/C++ counterparts, arrays in java are actually classes.

Say you have the following:
Code:
int[] arr;
arr = new int[3];

this is essentially the same a having somethign like this:
Code:
class int
{
//Array was defined to have 3 elements, so there are 3 data members
   int a;
   int b;
   int c;
   int getA();
   int getB();
   int getC();
 }


Now you are probbaly thinking, "if arrays are objects, then why can I do if(arr[1] == 8)?"

This is because when accessing elements of an array, you are dereferencing the array at a particular memory location. Think of it as calling the getter method for that particular location (Hence the getA(), getB(), and getC() methods in the class definition).

I hope all of this is clear to everyone. I realize my examples are not the best, but I think that they will suffice for the purpose of undersanding.
 
Upvote 0
*blushes*

This is what the forum exists for in the first place, right? To help people?

At any rate, I edited the post to fix a few typos (if you notice any more, let me know), and throw some italics in there to make it more understandable.

Also, I want to make a disclaimed that the section on arrays is not really exactly how it works internally, but by explaining it this way, it helps people understand it better. The way it is programmed is actually much more complex and, if you look at the actual source code, you'll likely quickly be in over your head.

Just wanted to add that so I don't get lashed out at by more experienced devs.
 
  • Like
Reactions: alostpacket
Upvote 0

BEST TECH IN 2023

We've been tracking upcoming products and ranking the best tech since 2007. Thanks for trusting our opinion: we get rewarded through affiliate links that earn us a commission and we invite you to learn more about us.

Smartphones