删除+添加后,片段未收到LiveData更新 [英] Fragment not receiving LiveData updates after remove + add
问题描述
我目前正在四处寻找与ViewModel
和LiveData
相关的fragment
生命周期.
I am currently playing around to get a hang of the fragment
's lifecycle in relation to ViewModel
and LiveData
.
我有2个fragments
,fragmentA
和fragmentB
.
我在每个fragment
的onCreate
方法中添加Observer
.
I have 2 fragments
, fragmentA
and fragmentB
.
I add the Observer
in the onCreate
method of each fragment
.
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
sharedViewModel = ViewModelProviders.of(getActivity()).get(SharedViewModel.class);
sharedViewModel.getText().observe(this, new Observer<CharSequence>() {
@Override
public void onChanged(CharSequence charSequence) {
editText.setText(charSequence);
}
});
}
每个fragment
都有一个按钮,用于更改共享ViewModel
Each fragment
has a button that changes LiveData
in the shared ViewModel
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
[...]
buttonOk.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
sharedViewModel.setText(editText.getText());
}
});
[...]
}
SharedViewModel
:
public class SharedViewModel extends ViewModel {
private MutableLiveData<CharSequence> text = new MutableLiveData<>();
public void setText(CharSequence input) {
text.setValue(input);
}
public LiveData<CharSequence> getText() {
return text;
}
}
当我单击一个按钮时,我将fragment
替换为另一个.
When I click a button, I replace the fragment
for the other one.
public class MainActivity extends AppCompatActivity {
Fragment fragmentA = new FragmentA();
Fragment fragmentB = new FragmentB();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container_a, fragmentA)
.commit();
}
}
public void switchToA(View v) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, fragmentA)
.commit();
}
public void switchToB(View v) {
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, fragmentB)
.commit();
}
}
Replace
导致fragment
被完全销毁,并在下一次添加时再次通过它的onCreate
方法运行.我可以确认在屏幕上放置的每个fragment
都调用了onCreate
,并且添加了Observer
.
但是,一旦我替换了fragment
并重新添加了它,它便完全停止了onChanged
中的任何更新.甚至它自己发送的那些. onChanged
不再被触发.我不明白为什么.
Replace
causes the fragment
to be fully destroyed and run through it's onCreate
method again the next time it is added. I can confirm that onCreate
is called for each fragment
placed onto the screen and the Observer
is added.
But once I replaced a fragment
and re-added it, it completely stops getting any updates in onChanged
. Even the ones it sent itself. onChanged
is just not triggered anymore. I don't understand why.
我实际上发现LiveData
类中的followig if
检查返回了第二次,我尝试添加Observer
(在将fragment
替换为第一个之后) ):
I actually found out that the followig if
check in the LiveData
class returns the 2nd time I try to add the Observer
(after replacing the fragment
for the first one):
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
if (owner.getLifecycle().getCurrentState() == DESTROYED) {
// ignore
return;
}
因此,不再添加Observer
.当我尝试重新添加fragment
时,为什么getCurrentState()
返回DESTROYED
?
Hence, the Observer
is not added anymore. Why does getCurrentState()
return DESTROYED
when I try to re-add the fragment
?
简而言之:删除fragment
时会删除Observer
,但是下次添加该片段时不会再添加另一个Observer
.
In short: the Observer
is removed when the fragment
is removed, but it doesn't add another Observer
the next time the fragment is added.
推荐答案
根据 Lifecycle.State.DESTROYED文档:
此事件之后,此生命周期将不再调度任何事件.
After this event, this Lifecycle will not dispatch any more events.
即DESTROYED
是终端状态,一旦销毁,生命周期将始终被销毁.
I.e., DESTROYED
is a terminal state and once it is destroyed, that Lifecycle will always be destroyed.
这意味着您可以通过两种正确的方式来做自己想做的事情:
This means there are two correct ways to do what you want:
-
每次调用
-
创建一个新的Fragment实例.由于删除Fragment时所有状态都被破坏,因此通过重用Fragment实例不会获得任何收益.
switchToA
或switchToB
时,Create a new Fragment instance each time you call
switchToA
orswitchToB
. Since all the state is destroyed when you remove a Fragment, you aren't gaining anything by reusing Fragment instances.
不要使用replace
,而要使用attach()
和detach()
(即,附加要显示的内容,分离要隐藏的内容).碎片在分离时仍保持其状态(不会被破坏),因此重新附加碎片会将其移回恢复状态.
Don't use replace
, but instead use attach()
and detach()
(i.e., attach the one you want to display, detach the one you want to hide). Fragments keep their state when detached (they aren't destroyed), so re-attaching it will move it back to resumed.
这篇关于删除+添加后,片段未收到LiveData更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!