Android检测片段何时分离

时间:2014-11-20 09:28:44

标签: android

我可以通过Fragments

轻松检测Activity何时附加到Activity.onAttachFragment()

但是如何在Activity中检测到某些Fragment与活动分离? 没有Activity.onDetachFragment()

是否正在修改Fragment并编写一些代码来通知Activity该状态是唯一的解决方案吗?

5 个答案:

答案 0 :(得分:7)

您可以使用界面在FragmentActivity

之间进行通信

类似的东西:

  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();
     }
  }

并在您的活动中:

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

修改

新方法是在onAttach中设置接口实例。

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

现在没有必要使用setCommunicator方法。

答案 1 :(得分:1)

您在片段生命周期中有回调。当片段不再附加到活动时,将调用onDetach()

答案 2 :(得分:1)

Mohammad's original answer接近我会做的。他已经更新它以利用Android提供的机制 - Fragment.onAttach(Context context)。在这种方法中,片段从系统中获取组件(即活动)并调用它。这打破了控制权的反转。

这是我首选的方法:

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);
        }
    }
}

在这个解决方案中,片段并没有决定它的周围环境。一些控件被赋予片段,因为它打破了连接本身。我们还没有完全拥有片段的分离,所以清除听众真的只是清理。

这是一种更明确,更不容易出现开发人员错误的替代方法,但也会产生额外的锅炉板(我更喜欢之前的方法,因为再见握手感觉就像是不必要的分心):

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);
        }
    }
}

答案 3 :(得分:1)

一种替代方法是:

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

如果视图为null,则必须分离片段。

答案 4 :(得分:0)

您可以使用 ViewModel 来更新主机活动。共享 ViewModel 可能是比旧的基于监听器的多态模型更好的选择。您可以关注official documentation

使用共享视图模型可以观察到数据、片段生命周期等。

sealed class FragmentStates {
    object Attached : FragmentStates()
    object Started : FragmentStates()
    object Stopped : FragmentStates()
    object DeAtached : FragmentStates()
}

class FragmentStateViewModel : ViewModel() {
    private val _fragmentState = MutableLiveData<FragmentStates>()
    val fragmentStates: LiveData<FragmentStates> get() = _fragmentState

    fun fragmentAttached() {
        _fragmentState.value = FragmentStates.Attached
    }

    fun fragmentDeAtached() {
        _fragmentState.value = FragmentStates.DeAtached
    }

}

class HostActivity : AppCompatActivity() {
    private val fragmentStateViewModel: FragmentStateViewModel by viewModels()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        fragmentStateViewModel.fragmentStates.observe(this, Observer {
          when(it) {
              FragmentStates.Attached -> {}
              FragmentStates.Started -> {}
              FragmentStates.Stopped -> {}
              FragmentStates.DeAtached -> {}
          }
        })
    }
}

class MyFragment: Fragment() {
    private val fragmentStateViewModel: FragmentStateViewModel by activityViewModels()

    override fun onAttach(context: Context) {
        super.onAttach(context)
        fragmentStateViewModel.fragmentAttached()
    }

    override fun onDetach() {
        super.onDetach()
        fragmentStateViewModel.fragmentDeAtached()
    }
}