tags:

views:

71

answers:

3

When you have a list activity and in onListItemClick() you need to obtain the selected item and then match it against various options, what is the efficient way to do it? switch case cannot be used since I want to match Strings. Is a very long if-else if ladder the only way to do it?

Basically the question is how to do something that normally would be done in switch statement with Strings.

+2  A: 

In Android it's advised to use an adapter or cursor, and you will use the position parameter to jump in the adapter or cursor to the given position.

Your adapter can be simple as an array, a database cursor, or a custom adapter too.

Pentium10
I would question the Android SDK knowledge of the one who down voted on this answer.
Pentium10
+1  A: 

You still can use switch with enums - you just have to convert a String input into an enum - or null, if you don't have an enum for it. Like this:

public enum Input {ONE, TWO, THREE, NULL}

and in the code

String selection = getInput();   // some internal magic to get the selectes list item
Input input = Enum.valueOf(Input.class, selection.toUpperCase().trim());
if (input == null) input = Input.NULL;
switch(input) {
  case ONE:   // "one" was selected
  case TWO:   // "two" was selected
  case THREE: // "three" was selected
  default:    // unrecognized / unhandled input
}

Please note, that I skipped the break statements to keep the example short.


Just learned, that if size and/or speed matters enums should be avoided in android development. So the pattern will work with old fashioned static consts too, just change

Input input = Enum.valueOf(Input.class, selection.toUpperCase().trim());

to

int input = decode(selection.toUpperCase().trim());

and make sure, you have the static fields ONE, TWO, ... set and a decoder implementation to convert a String input to one of your constants. Yes, it's much uglier, especially in the decoder, but that one can be hidden somewhere out of sight.

Andreas_D
good answer but for some reason enums are discouraged in android development
Janusz
No enums in android? Didn't know that.
Andreas_D
@Janusz, found something, could you please confirm, that the link I added to my answer explains the true reason for 'discouraged' use?
Andreas_D
Enums are available but google advises to not use them where speed matters: http://developer.android.com/guide/practices/design/performance.html#avoid_enums I would use them to get nice and clean code and get rid of them later if they are a problem with performance.
Janusz
Then if it's just for size/performance - I wander if this is the reason for all those downvotes...
Andreas_D
+1  A: 

I would typically try to create enums like Andreas_D posted but if that does not work you can fall back to a Map keyed on your strings with values pointing to some kind of interface or base type.

Something that roughly looks like this using the "Command" pattern.

EDIT: As requested here is an expanded example. This structure will net you the same overall characteristics of a switch statement keyed off a string. Of course the DoActionThing interface could be replaced by a base class.

public interface DoActionThing
{
    public void doSomething();
}

public class Sample
{
    private final String LIST_ITEM_1 = "Foo";
    private final String LIST_ITEM_2 = "Bar";

    private Map<String, DoActionThing> actions;

    public Sample()
    {
        actions = new HashMap<String, DoActionThing>();
        actions.put(LIST_ITEM_1, new DoActionThing()
        {
            @Override
            public void doSomething()
            {
                handleFooSelection();
            }
        });
        actions.put(LIST_ITEM_2,  new DoActionThing()
        {
            @Override
            public void doSomething()
            {
                handleBarSelection();
            }
        });
    }

    public void onListItemClick()
    {
    //Get the selected string from list
        String selected = ....
        DoActionThing dat = actions.get(selected);
        dat.doSomething();
    }
}
Tansir1
Nice answer. This is the way I do it in some of my Android apps.
Janusz
Could you please elaborate on the usage of Hash Maps?
Namratha
@Namratha It's not the most elegant solution but it gets the job done. The HashMap is keying off of strings so there are performance considerations to keep in mind. Using this to map GUI selection events should be fine.
Tansir1
@Tansir1: Thanks for the extremely helpful example. I have one question-the class must implement the interface isn't it?
Namratha
And do explain what you mean by 'keying off' of strings
Namratha
@Namratha The "actions" variable is map. The map's key type is a string. The value of a key is a "DoActionThing" type. Each "DoActionThing" is referenced by a key (a string). The "actions" map is created as a HashMap. Therefore it will use hashing algorithms on the map keys to find the values. Hashing over strings is less efficient than enums or primitive types. This is what I meant by "keying off".
Tansir1
@Namratha The "DoActionThing" interface in this example was implemented as anonymous inner classes. actions.put(LIST_ITEM_1, new DoActionThing(){ ....... });You can implement this interface on a traditional class or as anonymous inner classes. The "actions" map has to map from strings to another object type. Thus all the actions you want to perform must be referable as some shared type. In this case I chose an interface; a base class would work as well.
Tansir1
If I had another class that implemented doActions, then that class would have to implement doSomething(). But, how do I then go about doing what you've done above-adding entries into the map because now I have only one function doSomething() in the other class.
Namratha
I think you mean that you have one class that handles all the possible actions from selecting things in your list. In that case, you do not want to implement "DoActionThing" on that class. You should use anonymous inner classes like in the example. The anonymous inner classes then call your doActions class.
Tansir1
I recommend reading this to understand how anonymous inner classes are helpful.http://www.javaranch.com/campfire/StoryInner.jsp
Tansir1