Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android fragments 片段在删除+;添加_Android Fragments_Android Viewmodel_Android Livedata_Mutablelivedata - Fatal编程技术网

Android fragments 片段在删除+;添加

Android fragments 片段在删除+;添加,android-fragments,android-viewmodel,android-livedata,mutablelivedata,Android Fragments,Android Viewmodel,Android Livedata,Mutablelivedata,我目前正在研究片段的生命周期与ViewModel和LiveData的关系 我有两个片段,片段a和片段b。 我在每个片段的onCreate方法中添加Observer @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); sharedViewModel = ViewModelProviders.of(getActivity())

我目前正在研究
片段的生命周期与
ViewModel
LiveData
的关系

我有两个
片段
片段a
片段b
。 我在每个
片段的
onCreate
方法中添加
Observer

@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);
        }
    });
}
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;
    }
}
Replace
导致
片段
被完全销毁,并在下次添加时再次运行其
onCreate
方法。我可以确认为屏幕上放置的每个
片段
调用了
onCreate
,并且添加了
观察者
。 但是一旦我替换了
片段并重新添加它,它就完全停止了
onChanged
中的任何更新。甚至是它自己发送的那些
onChanged
不再触发。我不明白为什么

编辑:

事实上,我发现
if
LiveData
类中的检查返回了第二次,我尝试添加
观察者
(在第一次替换
片段之后):

@MainThread
公共无效观察(@NonNull LifecycleOwner owner,@NonNull Observer根据:

在此事件之后,此生命周期将不再调度任何事件

也就是说,
销毁
是一种终端状态,一旦销毁,该生命周期将始终被销毁

这意味着有两种正确的方法来做你想做的事情:

  • 每次调用
    switchToA
    switchToB
    时,都要创建一个新的片段实例。由于删除片段时所有状态都会被破坏,因此重用片段实例不会获得任何好处

  • 不要使用
    replace
    ,而是使用
    attach()
    detach()
    (即,附加要显示的片段,分离要隐藏的片段)。片段在分离时保持其状态(它们不会被销毁),因此重新附加它会将其移回恢复状态


  • 谢谢。所以我想对于ViewModel来说,再也没有必要重用被删除的片段实例了,因为我们用最新的数据更新了新的实例?当您销毁片段时,它的ViewModel也会被销毁,所以这当然是选项1的一个缺点。如果您使用选项1,它可能对这些更有意义要成为在片段被销毁时不会被销毁的活动范围的ViewModels,我实际上在问题中使用了一个活动范围的ViewModel。但是一旦片段通过onDestroy,我们总是必须创建一个新实例,就像你在
    1中解释的那样。
    ,对吗?啊,错过了你使用的是活动范围的ViewModel。在在这种情况下,是的,选项1可以很好地工作。但是这是一个bug吗?我觉得如果片段再次创建,它的生命周期应该“复活”
    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;
        }
    }
    
    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();
        }
    }
    
    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        assertMainThread("observe");
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }