1. Download our Official Android App: Forums for Android!

Apps Weird Issue Using onSharedPreferenceChanged()

Discussion in 'Android Development' started by Laxidasical, Aug 25, 2011.

  1. Laxidasical

    Laxidasical Newbie
    Thread Starter
    Rank:
    None
    Points:
    16
    Posts:
    25
    Joined:
    Aug 25, 2011

    Aug 25, 2011
    25
    3
    16
    Chicago
    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 (Text):
    1.  
    2. public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)
    3. {
    4.     Toast.makeText(this, key, 2000).show(); // displays "myKey" (without quotes)
    5.     if (key == "myKey") {Toast.makeText(this, "It Worked!!!", 2000).show();}  //does nothing!!!
    6. }
    7.  

    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 (Text):
    1.  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!!!
     

    Advertisement

  2. alostpacket

    alostpacket Over Macho Grande?
    Rank:
    None
    Points:
    513
    Posts:
    7,972
    Joined:
    Nov 29, 2009

    Nov 29, 2009
    7,972
    3,603
    513
    Android App Developer
    NY
    A key is a String.

    When comparing String in Java, you need to use the .equals( obj ) method

    So

    Code (Text):
    1.  
    2. if ( string1.equals("myString") )
    3. {
    4.    //do something exciting
    5. }
    6.  
    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!

    :)
     
  3. alostpacket

    alostpacket Over Macho Grande?
    Rank:
    None
    Points:
    513
    Posts:
    7,972
    Joined:
    Nov 29, 2009

    Nov 29, 2009
    7,972
    3,603
    513
    Android App Developer
    NY
    Also welcome to AF! :)
     
  4. jonbonazza

    jonbonazza Android Expert
    Rank:
    None
    Points:
    163
    Posts:
    1,930
    Joined:
    Jul 13, 2010

    Jul 13, 2010
    1,930
    457
    163
    Male
    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.
     
  5. Laxidasical

    Laxidasical Newbie
    Thread Starter
    Rank:
    None
    Points:
    16
    Posts:
    25
    Joined:
    Aug 25, 2011

    Aug 25, 2011
    25
    3
    16
    Chicago
    Thanks alostpacket & jonbonazza,

    I actually wound up using string1.contains("string2"), but I think .equals() is a little better solution. So you can't compare strings using ==, huh?!?!?! Seems odd to me, but so be it!

    On to post my next issue...
     
  6. alostpacket

    alostpacket Over Macho Grande?
    Rank:
    None
    Points:
    513
    Posts:
    7,972
    Joined:
    Nov 29, 2009

    Nov 29, 2009
    7,972
    3,603
    513
    Android App Developer
    NY
    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 :)
     
  7. Laxidasical

    Laxidasical Newbie
    Thread Starter
    Rank:
    None
    Points:
    16
    Posts:
    25
    Joined:
    Aug 25, 2011

    Aug 25, 2011
    25
    3
    16
    Chicago
    LOL - Hope you feel better!
     
  8. jonbonazza

    jonbonazza Android Expert
    Rank:
    None
    Points:
    163
    Posts:
    1,930
    Joined:
    Jul 13, 2010

    Jul 13, 2010
    1,930
    457
    163
    Male

    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 (Text):
    1.  
    2. int numDogs;
    3. Animal dog;
    4.  
    In our example, int is a primitive, and Animal is a pointer. If we tried to do the following:
    Code (Text):
    1.  
    2. numDogs = 8;
    3. if(numDogs == 8)
    4.    Toast.makeText(this, "Blah...", Toast.LENGTH_LONG).show();
    5.  
    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 (Text):
    1.  
    2. int numDogs;
    3. String dogName;
    4. dogName = "Henry";
    5. numDogs = 8;
    6.  
    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 (Text):
    1.  
    2. if(dogName == "Henry")
    3.    Log.v("TAG","HENRY!!!");
    4.  
    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 (Text):
    1.  
    2. Button b = (Button)findViewById(R.id.MyButton);
    3.  
    4. void onClick(View v)
    5. {
    6.     if(b == v)
    7.        Log.v("TAG", "Button clicked!");
    8.   }
    9.  
    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 (Text):
    1.  
    2. int[] arr;
    3. arr = new int[3];
    4.  
    this is essentially the same a having somethign like this:
    Code (Text):
    1.  
    2. class int
    3. {
    4. //Array was defined to have 3 elements, so there are 3 data members
    5.    int a;
    6.    int b;
    7.    int c;
    8.    int getA();
    9.    int getB();
    10.    int getC();
    11.  }
    12.  

    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.
     
    Laxidasical and alostpacket like this.
  9. Laxidasical

    Laxidasical Newbie
    Thread Starter
    Rank:
    None
    Points:
    16
    Posts:
    25
    Joined:
    Aug 25, 2011

    Aug 25, 2011
    25
    3
    16
    Chicago
    Fantastic explanation Jon, this clears up a lot of confusion! I'm still not ecstatic about this particular nuance of Java, but at least I have a good understanding of how it works now.

    I'm definitely bookmarking this post...
     
  10. alostpacket

    alostpacket Over Macho Grande?
    Rank:
    None
    Points:
    513
    Posts:
    7,972
    Joined:
    Nov 29, 2009

    Nov 29, 2009
    7,972
    3,603
    513
    Android App Developer
    NY
    ^ you see that? I told ya, brilliant :D Jon is one of our most helpful devs around here :)

    Edit: not to mention it is very fun to help people who have specific questions and are willing to do the work and want to learn :)
     
  11. jonbonazza

    jonbonazza Android Expert
    Rank:
    None
    Points:
    163
    Posts:
    1,930
    Joined:
    Jul 13, 2010

    Jul 13, 2010
    1,930
    457
    163
    Male
    *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.
     
    alostpacket likes this.

Share This Page

Loading...