0

So I am trying to get some experience with Fragments, but I'm finding some roadblocks.

My current situation is as follows.

I have an activity that displays a List whose content is determined by Extra Intent parameters sent from the 'calling' activity.

This List activity uses ListFragment declared in the XML like so:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent" android:background="@color/black">
    <fragment class="com.pixlworks.NLC.DirectoryBrowse$ListingFragment"
              android:id="@+id/listing"
              android:layout_width="match_parent"
              android:layout_height="match_parent" />

</FrameLayout>

Currently I get the parameter that indicates the type of content directly in the Fragment by accessing the Extra data of the Activity Intent (or saved Bundle if available):

public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    if (savedInstanceState != null)
        mListingType = savedInstanceState.getString(Utils.DIRECTORY_TYPE_STORE_KEY);
    else
        mListingType = getActivity().getIntent().getStringExtra(Utils.DIRECTORY_TYPE_STORE_KEY);

    // get content by type, create and set the adapter

}

Now part of my problem is that I am not sure this is the right way to 'pass' that parameter from the Activity to the Fragment.

On top of that, I am getting issues with this setup when using the Action Bar's UP Navigation. When I click on an item in this List Activity it goes to another activity showing the details of the selected item. From this detail activity:

  • If I use the back button, the List Activity is brought back from the stack as usual and everything works fine.

  • If I use the ActionBar's UP (despite following steps here), it would seem that a new instance is created instead of using the one in the stack and this new instance obviously is not getting the Extra parameter in the Intent. Since I am expecting the value to exist in the saved Bundle or in the Intent, my app crashes in this situation.

So to boil things down, I am not sure which of these to follow and how to make them work properly with 'UP' navigation:

A) Hold the 'type' parameter in a field in the Activity and save it in the Activity's Bundle onSaveInstanceState. In which case I am not sure how to then pass the value to the Fragment. In this case I would just need to make sure that UP calls the existing instance of the Activity List

B) Continue with my current setup of saving the value in the Fragment instead of the Activity, but again, how to handle the UP navigation correctly?

I know it is kind of multiple things I am asking here at the same time, but they are all connected, so I hope that I can get some help on this.

Thanks for any help in advance!

RobertoCuba
  • 881
  • 9
  • 25

1 Answers1

0

The UP navigation makes more sense to be used within the same activity level. That is the intention of the codes that you followed in the developers page. Because you started a new activity, if you want to return to previous activity like the back button you will need to call finish() to destroy the details activity first.

As for passing data from activity to fragment, when you create a new instance of fragment, you can pass the data to it as bundle, for example:

// in fragment class
public static MyFragment newInstance(Bundle arg) {
    MyFragment f = new MyFragment();
    f.setArguments(arg);
    return f;
}

When you create a new fragment, you can call:

// in activity
Bundle arg = new Bundle();
int info = ...;
arg.putInt("INFO",info); 
...
MyFragment mFragment = MyFragment.newInstance(arg);

Finally, to get the data in fragment:

int info = getArguments().getInt("INFO");
...

Instead of directly calling MyFragment mFragment = new MyFragment() to instantiate the fragment, you should use a static method to instantiate it. This is to prevent some crashes which might happen if you rotate the screen and the framework complains that it couldn't find a public empty constructor.


UPDATE

To answer your questions:

1) Say you start from activity A -> activity B. Then in activity B you press the up button. By logic of use, the up button will not bring you back to activity A, because its intention is to navigate one level up,but still inside, activity B. To return to activity A, you need to call finish() to destroy activity B first.

2) If your fragment is created in xml, you still can set arguments. In your xml, you set an id for the fragment android:id="@+id/fragment_id", then

// in activity
FragmentManager fm = getSupportFragmentManager(); // or getFragmentManager() if you don't have backward compatibility
MyFragment mFragment = fm.findFragmentById(R.id.fragment_id);
Bundle arg = new Bundle();
// put data blah blah
mFragment.setArguments(arg);

Just make sure you set the arguments before you use the fragment.

Simply said, intent is used when you pass data between calling activities; bundle is used when you want to pass data from activity to fragment.

Neoh
  • 15,906
  • 14
  • 66
  • 78
  • Thank you for your response. It kind of provided me with more questions than answers I think. 1) What do you mean that the UP navigation as I am looking at it is more for 'within the same activity level'? 2) In the link I put, in the section "Navigate Up to Parent Activity) it says that using that bit of code, the UP navigation will bring forth any instance of the Activity already running. But that doesn't seem to happen 3) The Fragment code you provide works if I was instantiating and adding teh Fragment programmatically, but I have it declared in the XML. – RobertoCuba Sep 19 '13 at 03:58
  • Is creating and adding the Fragment programmatically the only way to do this? – RobertoCuba Sep 19 '13 at 04:02
  • Thanks again for the response. 1) I guess I still don't understand how one goes 'UP' within the same activity. I thought this whole deal of the UP navigation was to travel along logical Parent-Child Activity trees (hence all the 'Parent' activity setup in the manifest).In the end, what you are saying about calling finish() is exactly what the code I mentioned is supposed to do behind the scenes, yet it doesn't do it. It still creates a new instance. – RobertoCuba Sep 19 '13 at 04:28
  • 2) The Fragment code you put would be best in the activities onCreate() I assume, but which Fragment callback would be best to use those arguments for setup? onActivityCreated()? Sorry I am prolonging this, but you indeed helped me. – RobertoCuba Sep 19 '13 at 04:31
  • Apparently I was wrong about (2). Putting that code in on the activity's onCreate(). It throws an error: java.lang.IllegalStateException: Fragment already active which I guess comes from the fact that the system already instantiated the Fragment from being declared in the XML... – RobertoCuba Sep 19 '13 at 04:40
  • Yes, if you declare the fragment in xml then it will automatically instantiate the fragment when you setcontentview, so you can ignore the fragment codes. As for the up navigation, it is correct to see it as a parent-child navigations. However, if your intention is simply to return to the previous activity, then under `onOptionsItemSelected` in `case android.R.id.home:` you just call `finish()` – Neoh Sep 19 '13 at 04:49
  • 1
    I ended up just instantiating the Fragment on the activity's onCreate() and just passing the Bundle then. It seems that when declared on the XML, by the Activiy's onCreate using setArguments() on the Fragment is just too late on the Fragment's lifecycle. On the UP matter, I found this http://stackoverflow.com/a/17342137/977696. What would be the better approach? To use finish() like you mention? or to put launchMode as "singleTop" on the manifest? I tested quickly and both seem to have the same result. Thanks again for all the help. – RobertoCuba Sep 19 '13 at 05:14
  • There is no difference if you don't need to pass new intent between activities, otherwise you might need to set `android:singleTop` or `android:singleTask` in order to return to your previous activity. More details can be found here :http://www.intridea.com/blog/2011/6/16/android-understanding-activity-launchmode – Neoh Sep 19 '13 at 05:55