Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android detect when fragment is detached

Tags:

android

I can easily detect when Fragments are attached to Activity via Activity.onAttachFragment()

But how can I detect in Activity that some Fragment is detached from activity? There is no Activity.onDetachFragment()

Is subcclasing Fragment and write some code to notify Activity about that state is the only solution?

like image 418
Dominik Suszczewicz Avatar asked Nov 20 '14 09:11

Dominik Suszczewicz


4 Answers

you can use interface for communicating between Fragment and Activity

something like this :

  public Class MyFragment extends Fragment {
    FragmentCommunicator communicator;
    public void setCommunicator(FragmentCommunicator communicator) {
      this.communicator = communicator;
    }
    @Override
    public void OnDetach() {
      communicator.fragmentDetached();
    }
    ...

     public Interface FragmentCommunicator {
        public void fragmentDetached();
     }
  }

and in your activity :

 public Class MyActivity extends Activity Implements FragmentCommunicator {
   ...
   MyFragment fragment = new MyFragment();
   fragment.setCommunicator(this);
   ...
   @Override 
   public void fragmentDetached() {
       //Do what you want!
   }
 }

Edit:

the new approach is setting interface instance in onAttach.

public void onAttach(Activity activity) {
    if (activity instanceof FragmentCommunicator) {
        communicator = activity;
    } else {
        throw new RuntimeException("activity must implement FragmentCommunicator");
    }
}

now there is no need to have setCommunicator method.

like image 54
Mohammad Rahchamani Avatar answered Oct 22 '22 09:10

Mohammad Rahchamani


Mohammad's original answer is close to I would do. He has since updated it to leverage a mechanism provided by Android - Fragment.onAttach(Context context).In that approach, the fragment grabs components (ie, the activity) from the system and calls into it. This breaks inversion of control.

Here is my preferred approach:

public class MyActivity extends AppCompatActivity {

    @Override
    public void onAttachFragment(Fragment fragment) {
        super.onAttachFragment(fragment);
        if (fragment instanceof MyFragment) {
            ((MyFragment) fragment).setListener(mMyFragmentListener);
        }
    }

    private final MyFragment.Listener mMyFragmentListener = new MyFragment.Listener() {
        @Override
        public void onDetached(MyFragment fragment) {
            fragment.setListener(null);
        }

        // implement other worker methods.
    };
}

public class MyFragment extends Fragment {

    @Nullable
    private Listener mListener;

    public void setListener(@Nullable Listener listener) {
        mListener = listener;
    }

    public interface Listener {
        void onDetached(MyFragment fragment);

        // declare more worker methods here that leverage the connection.
    }

    @Override
    public void onDetach() {
        super.onDetach();

        if (mListener != null) {
            mListener.onDetached(this);
        }
    }
}

In this solution, the fragment doesn't dictate it's surroundings. Some control is given the to fragment in that it breaks the connection itself. We also already don't own the detaching of the fragment anyways, so clearing the listener is really just cleanup.

Here is an alternative approach that is more explicit, less prone to developer error, but also creates extra boiler plate (I prefer the previous approach because the goodbye handshake feels like an unnecessary distraction):

public static class MyActivity extends AppCompatActivity {

    @Override
    public void onAttachFragment(Fragment fragment) {
        super.onAttachFragment(fragment);
        if (fragment instanceof MyFragment) {
            ((MyFragment) fragment).setListener(mMyFragmentListener);
        }
    }

    private final MyFragment.Listener mMyFragmentListener = new MyFragment.Listener() {
        @Override
        public void onDetached(MyFragment fragment) {
            fragment.setListener(null);
        }

        // implement other worker methods.
    };
}

public static class MyFragment extends Fragment {

    @Nullable
    private Listener mListener;

    public void setListener(@Nullable Listener listener) {
        mListener = listener;
    }

    public interface Listener {
        void onDetached(MyFragment fragment);

        // declare more worker methods here that leverage the connection.
    }

    @Override
    public void onDetach() {
        super.onDetach();

        if (mListener != null) {
            mListener.onDetached(this);
        }
    }
}
like image 22
methodsignature Avatar answered Oct 22 '22 07:10

methodsignature


You have a callback in the fragment life cycle. onDetach() is called when fragment is no longer attached to activity.

like image 1
N Sharma Avatar answered Oct 22 '22 07:10

N Sharma


An alternative would be:

mFragmentManager.findFragmentByTag("Tag").getView()

If the view is null the fragment must be detached.

like image 1
KaRa Avatar answered Oct 22 '22 07:10

KaRa