3

我目前正在玩弄与和fragment相关的生命周期。ViewModelLiveData

我有2fragments和. 我在 each 的方法中添加了。 fragmentAfragmentBObserveronCreatefragment

@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都有一个按钮,可以LiveData在共享中更改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

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我可以确认onCreate每个fragment放置在屏幕上的都调用它并Observer添加。但是,一旦我替换了 afragment并重新添加了它,它就完全停止在onChanged. 甚至是它自己发送的那些。onChanged只是不再触发。我不明白为什么。

编辑:

我实际上发现类中的后续if检查LiveData返回我第二次尝试添加Observer(在替换fragment第一个之后):

@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
    assertMainThread("observe");
    if (owner.getLifecycle().getCurrentState() == DESTROYED) {
        // ignore
        return;
    }

因此,Observer不再添加。为什么我尝试重新添加时getCurrentState()返回?DESTROYEDfragment

简而言之:Observer删除时删除了,但下次添加片段时fragment不会添加另一个。Observer

4

1 回答 1

5

根据Lifecycle.State.DESTROYED 文档

在此事件之后,此生命周期将不再派发任何事件。

即,DESTROYED是一个终止状态,一旦它被销毁,该生命周期将永远被销毁。

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

  1. 每次调用switchToA或时创建一个新的 Fragment 实例switchToB。由于删除 Fragment 时所有状态都将被销毁,因此重用 Fragment 实例不会获得任何收益。

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

于 2018-11-03T15:59:32.200 回答