Home - Programming - Android Fragment Frustration

Non-programmers, skip to the next entry...

Android does a sketchy job of handling what it calls Fragments. These are chunks of logic, ostensibly connected to a View, that encapsulate a bit of logic and layout. Conceptually equivalent to Delphi frames, Struts Tiles, that sort of thing. One problem with fragments -- and there are a few -- is the violation of the encapsulation when handling events for returning activities launched from a fragment. If you have onActivityResult defined in the FragmentActivity that owns the fragment that launched the activity, the FragmentActivity gets the signal. If you don't, the fragment gets the signal.

Completely counter-intuitive. You'll waste a whole morning trying to figure out what's going wrong. I think the original idea was to allow the activity to have insight into the returning call so it can react to it. Problem is, it's not well documented -- at least I couldn't find anything that mentioned it.

When an activity launched from a fragment returns, the FragmentActivity.onActivityResult's requestCode has the request code used to launch the intent along with a fragment index stuffed into the high-order bits. Don't get me started with what an ugly hack that is, but if you do a shift-left 16 on the request code, you can at least tell if what you got back was a response intended for a fragment. Don't bother trying to do anything intelligent with that number -- it's a value used somewhere in the fragment manager that you don't have access to. But if you then pass the event to super.onActivityResult, the framework will finish the job of routing the event. So here's what that ends up looking like:

    @Override
    public void onActivityResult( int requestCode, int resultCode, Intent data ) {

        // Is this response intended for a fragment?
        int fragmentindex = ( requestCode >> 16 );
        if ( fragmentindex != 0 ) {
            // Yes.  Pass it on...
            super.onActivityResult( requestCode, resultCode, data );
        }
        else {
            // No, it's a response to an activity launched locally.
            switch( requestCode ) {
            case SomeRequestCode:
                someMethod();
                break;
            }
        }
    }

You're welcome. Good luck.

Update 10/21/2014: This was an entry from my old blog that got a lot of "thank you"s. I really get a kick out of the fact that this helped people, and it really aggravates me that GoDaddy discontinued their blogging service.

More to come...
Todd Grigsby