Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it preferable to use Activity.onAttachFragment or Fragment.onAttach to communicate between an Activity and a nested fragment?

The Android documentation suggests that to communicate from an activity to a hosted fragment, the fragment can define a callback interface and require that the host activity implement it. The basic pattern involves implementing onAttach in your fragment, and casting the activity to a callback inteface. See http://developer.android.com/guide/components/fragments.html#CommunicatingWithActivity.

Here's an example of providing a fragment some initialization data, as well as listening for a navigation callback.

public class HostActivity extends Activity implements FragmentHost {   @Override   UiModel getUiModel() {     return mUiModel;   }   @Override   FragmentNavListener getNavListener() {     return mNavListener;   } ... }  public class HostedFragment extends Fragment {   @Override   public void onAttach(Activity activity) {     super.onAttach(activity);     if (activity instanceof FragmentHost) {       FragmentHost host = (FragmentHost) activity;       setUiModel(host.getUiModel());       setNavListener(host.getFragmentNavListener());     }   }   ... } 

Compare this to using onAttachFragment in the host activity to explicitly initialize the fragment:

public class HostActivity extends Activity {   @Override   public void onAttachFragment(Fragment fragment) {     super.onAttachFragment(fragment);     if (fragment instanceof HostedFragment) {       HostedFragment hostedFragment = ((HostFragment) fragment);       hostedFragment.setUiModel(mUiModel);       hostedFragment.setNavListener(mNavListener);     }   }   ... } 

To me, it seems like the first pattern has some drawbacks:

  1. It makes the fragment harder to use from different activities, since since all of those activities must implement the required interface. I can imagine cases where a given fragment instance doesn't require being fully configured by the host activity, yet all potential host activities would need to implement the host interface.
  2. It makes the code slightly harder to follow for someone unfamiliar with the pattern being used. Initializing the fragment in onFragmentAttached seems easier to follow, since the initialization code lives in the same class that creates the fragment.
  3. Unit testing using a library like Robolectric becomes harder, since when calling onAttach, you must now implement FragmentHost rather than just calling onAttach(new Activity().

For those of you who've done activity to fragment communication, what pattern do you find preferable, and why? Are there drawbacks to using onAttachFragment from the host activity?

like image 416
user1519108 Avatar asked Oct 15 '12 17:10

user1519108


People also ask

Which one is better fragment or activity?

Activities are an ideal place to put global elements around your app's user interface, such as a navigation drawer. Conversely, fragments are better suited to define and manage the UI of a single screen or portion of a screen. Consider an app that responds to various screen sizes.

What is onAttach in fragment in Android?

onAttach(Activity) called once the fragment is associated with its activity. onCreate(Bundle) called to do initial creation of the fragment. onCreateView(LayoutInflater, ViewGroup, Bundle) creates and returns the view hierarchy associated with the fragment.


1 Answers

I cant speak personally with respect to testing but there is alternatives to fragment / activity callback interface communication.

For example you can use a event bus to decouple the fragments and your activity. An excellent event bus can be found here:

Otto - An event Bus by Square

It is actively being developed by some very talented engineers at Square. You can also use the LocalBroadcastManager that is packaged in the Android Support Library.

LocalBroadcastManager

Eric Burke from square has a presentation where he mentions both which can be found here:

Android App Anatomy

like image 61
Marco RS Avatar answered Sep 28 '22 01:09

Marco RS