Search code examples
javaandroidcircular-dependency

Best way to resolve cyclic dependency between Activity and Fragment


I have this simple problem:

An activity contains a fragment. Both want to communicate with each other.

The fragment wants to inform the activity about certain interactions. Therefore it defines the OnFragmentInteractionListener interface which is implemented by the activity. This is already part of the Android Studio fragment template, so nothing new here.

The activity wants to inform the fragment about the back button being pressed. Therefore it defines the OnBackPressedListener interface which is implemented by the fragment.

class MainActivity extends AppCompatActivity implements MyFragment.OnFragmentInteractionListener {

    ...

    @Override
    public void onFragmentInteraction(Uri uri) {
        ...
    }

    interface OnBackPressedListener {
        boolean onBackPressed();
    }
}

class MyFragment extends Fragment implements MainActivity.OnBackPressedListener {

    ...

    @Override
    public boolean onBackPressed() {
        ...
    }

    interface OnFragmentInteractionListener {
        void onFragmentInteraction(Uri uri);
    }
}

IMHO a simple design that, unfortunatley, doesn't work. "Cyclic inheritance involving ..." is the message from Android Studio.

I would have expected that compilation error if I used nested classes instead of interfaces as the classes' static initializers might be cyclic dependent on each other. I don't see that problem with interfaces but I'm sure there's a good reason why it's not allowed.

The easiest way to resolve this is making one of the interfaces a package-level interface. But I wonder if this is the way to go. And if so: which one should be package-level.


Solution

  • You can have a BroadcastListener attached to the Fragment using a register call.

    Please do not forget to unregister the listener in onStop or onPause if you plan to interact with the UI or it will cause exceptions.

    Now the simple way is, override the onBackPressed inside your activity and when it gets hit, broadcast an event and let your fragment know. Simple and shouldn't be too problematic to handle.

    I personally prefer this approach to send messages to all my Fragments. Another approach as you yourself said is declaring a package wide interface and doing the stuff that you wanted as you already wrote. Nothing wrong with this either, it's just Java being Java.