Android 使用自定义构造函数重新创建片段



是否可以重新创建依赖于构造函数传递的LiveData的片段?我可以在重新创建后使用LiveData或ViewModel与LiveData。

我有一个视图Pager2,它使用适配器创建片段。片段需要 LiveData 才能正常工作。在屏幕旋转之前一切正常,因为那时 android 想要重新创建片段,但使用非 arg 构造函数,所以我无法再获得 LiveData。有什么可以帮助解决问题的吗?

片段

public class SensorFragment extends Fragment {
private SensorViewModel viewModel;
public static SensorFragment withSensor(LiveData<Sensor> sensor) {
SensorViewModelFactory factory = new SensorViewModelFactory(sensor);
SensorViewModel viewModel = factory.create(SensorViewModel.class);
SensorFragment sensorFragment = new SensorFragment();
sensorFragment.setViewModel(viewModel);
return sensorFragment;
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
SensorFragmentBinding binding = DataBindingUtil
.inflate(inflater, R.layout.sensor_fragment, container, false);
binding.setLifecycleOwner(this);
binding.setViewModel(viewModel);
return binding.getRoot();
}
private void setViewModel(SensorViewModel viewModel) {
this.viewModel = viewModel;
}
}

视图模型工厂,用于使用自定义构造函数创建视图模型

public class SensorViewModelFactory implements ViewModelProvider.Factory {
private LiveData<Sensor> sensor;
public SensorViewModelFactory(LiveData<Sensor> sensor) {
this.sensor = sensor;
}
@NonNull
@Override
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
return (T) new SensorViewModel(sensor);
}
}

ViewPager2 创建片段的适配器。

public class SensorAdapter extends FragmentStateAdapter {
private List<LiveData<Sensor>> sensors;
...
@NonNull
@Override
public Fragment createFragment(int position) {
return SensorFragment.withSensor(sensors.get(position));
}
...
}

保存视图页r2的片段

public class ThermometerFragment extends Fragment {
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
ThermometerFragmentBinding binding =
DataBindingUtil.inflate(inflater, R.layout.thermometer_fragment,
container, false);
ThermometerViewModel viewModel = ViewModelProviders.of(this)
.get(ThermometerViewModel.class);
SensorAdapter sensorAdapter = new SensorAdapter(this);
viewModel.getThermometer().observe(this, thermometer ->
sensorAdapter.setSensors(thermometer.getSensors()));
binding.setAdapter(sensorAdapter);
return binding.getRoot();
}
}

编辑我已经像这样更改了传感器片段(现在它可以工作了(

public class SensorFragment extends Fragment {
private LiveData<Sensor> sensor;
public static SensorFragment withSensor(LiveData<Sensor> sensor) {
SensorFragment sensorFragment = new SensorFragment();
sensorFragment.setSensor(sensor);
return sensorFragment;
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
SensorFragmentBinding binding = DataBindingUtil
.inflate(inflater, R.layout.sensor_fragment, container, false);
SensorViewModel viewModel = ViewModelProviders.of(this).get(SensorViewModel.class);
if (sensor != null)
viewModel.setSensor(sensor);
binding.setLifecycleOwner(this);
binding.setViewModel(viewModel);
return binding.getRoot();
}
public void setSensor(LiveData<Sensor> sensor) {
this.sensor = sensor;
}
}

IMO,您的活动应该创建/初始化一个视图模型,并在 ViewPager 中与其片段共享相同的视图模型。

例:

我的活动.java:

public class MyActivity extends AppCompatActivity{
@Override
void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState)
setContent(...)
MyViewModel myViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
...
}
}

在您的片段中:

我的片段.java:

public class MyFragment1 extends Fragment {
@Override
void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState)
setContent(...)
MyViewModel myViewModel = ViewModelProviders.of(getActivity()).get(MyViewModel.class);
...
}
}

原因是您的 ViewModel 在重新创建活动时不会被销毁。您在 ViewModel 中的所有数据都保持原样。它在方向变化中幸存下来。

有一种方法可以在一个活动的两个单独片段中访问视图模型的一个实例。只需将活动传递到片段中的ViewModelProviders.of(getActivity())方法即可。

ThermometerFragmentSensorFragment访问视图中,像这样访问模型:

ThermometerViewModel viewModel = ViewModelProviders.of(getActivity())
.get(ThermometerViewModel.class);

通常,对视图模型的引用存储在片段中,而不是实时数据中。当您需要访问实时数据时,只需通过视图模型获取即可。

最新更新