我可以通过Fragments
Activity
何时附加到Activity.onAttachFragment()
但是如何在Activity
中检测到某些Fragment
与活动分离?
没有Activity.onDetachFragment()
是否正在修改Fragment
并编写一些代码来通知Activity
该状态是唯一的解决方案吗?
答案 0 :(得分:7)
您可以使用界面在Fragment
和Activity
类似的东西:
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()
}
}