有必要将数据放入LiveData中以发送给回调。在这种方法中:
public void setData(List<Data> data) {
this.currentData.setValue((Data) data);
}
根据文档setValue由MutableLiveData调用,我用MutableLiveData替换了ViewModel中的LiveData,但是无论如何,当我打开所需的片段时,应用程序崩溃了
java.lang.ClassCastException: androidx.room.RoomTrackingLiveData cannot be cast to androidx.lifecycle.MutableLiveData
at avocado.droid.ptitsami.room.DataViewModel.<init>(DataViewModel.java:24)
at avocado.droid.ptitsami.room.DataViewModel$ModelFactory.create(DataViewModel.java:54)
at androidx.lifecycle.ViewModelProvider$FactoryWrapper.create(ViewModelProvider.java:268)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:179)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:147)
at avocado.droid.ptitsami.fragment.DataFragment.onCreateView(DataFragment.java:57)
如何解决?
ViewModel
public class DataViewModel extends AndroidViewModel {
MutableLiveData<Data> currentData;
DataRepository repository;
public DataViewModel(@NonNull Application application, final int verseId) {
super(application);
int verseId1 = verseId;
repository = new DataRepository(application);
currentData = (MutableLiveData<Data>) repository.getById(verseId);
}
public LiveData<Data> getById() {
return currentData;
}
public void setData(List<Data> data) {
this.currentData.setValue((Data) data);
}
public static class ModelFactory extends ViewModelProvider.NewInstanceFactory {
@NonNull
private final Application application;
private final int dataId;
private final DataRepository repository;
public ModelFactory(@NonNull Application application, int id) {
super();
this.application = application;
this.dataId = id;
repository = new DataRepository(application);
}
@NonNull
@Override
public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
if (modelClass == DataViewModel.class) {
return (T) new DataViewModel(application, dataId);
}
return null;
}
}
片段
public class DataFragment extends Fragment {
private int dataId;
private static final String KEY_DATA_ID = "KEY_DATA_ID";
public TextView tvTitle;
public DataFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootViewRead = inflater.inflate(R.layout.fragment_data, container, false);
Toolbar toolbar = rootViewRead.findViewById(R.id.toolbar);
AppCompatActivity activity = (AppCompatActivity) getActivity();
if (activity != null) {
activity.setSupportActionBar(toolbar);
}
setHasOptionsMenu(true);
tvTitle = (TextView) rootViewRead.findViewById(R.id.text);
DataViewModel.ModelFactory factory = new DataViewModel.ModelFactory(
getActivity().getApplication(), getArguments().getInt(KEY_DATA_ID));
final DataViewModel model = ViewModelProviders.of(this, factory)
.get(DataViewModel.class);
model.getById().observe(this, new Observer<Data>() {
@Override
public void onChanged(Data data) {
model.setData((List<Data>) data);
}
});
return rootViewRead;
}
public static DataFragment forData(int dataId) {
DataFragment fragment = new DataFragment();
Bundle args = new Bundle();
args.putInt(KEY_DATA_ID, dataId);
fragment.setArguments(args);
return fragment;
}
存储库
public class DataRepository {
private DatabaseCopier db;
DataRepository(Application application) {
db = DatabaseCopier.getInstance(application);
}
LiveData<Data> getById(int id) {
return db.getDatabase().dataDao().getById(id);
}
答案 0 :(得分:0)
尝试将源添加到currentData
,并将currentData
从MutableLivaData更改为MediatorLiveData。
LiveData<Data> data = repository.getById(verseId);
currentData.addSource(data, observer);
答案 1 :(得分:0)
这里有很多奇怪的地方。
在ViewModel中,您有一个用于LiveData的获取器和设置器:
public LiveData<Data> getById() {
return currentData;
}
public void setData(List<Data> data) {
this.currentData.setValue((Data) data);
}
在LiveData的观察者中,您称为LiveData的二传手?
model.getById().observe(this, new Observer<Data>() {
@Override
public void onChanged(Data data) {
model.setData((List<Data>) data);
}
});
那没有道理!调用observe
方法时,模型已具有该数据集!因此,您无需致电setData
。没有主要问题,这将造成无休止的循环!
现在是您的主要问题:
androidx.room.RoomTrackingLiveData cannot be cast to androidx.lifecycle.MutableLiveData
房间数据只能加载到LiveData。原因是Room一旦数据库的内容发生更改,Room始终保持链接并自动更新它!但是,因此您不能更改LiveData的内容!
所以请解释原因
有必要将数据放入LiveData中以发送给回调。
您必须更改:
//MutableLiveData<Data> currentData;
LiveData<Data> currentData;
和
model.getById().observe(this, new Observer<Data>() {
@Override
public void onChanged(Data data) {
//model.setData((List<Data>) data); <- this creates an endless loop
// do here what you want to do with the content of the data
// if you need to pass it to the viewmodel, do it, but do not call `setValue`
}
});
对于特定的用例,MediatorLiveData可能是合理的,但是为此,您必须详细说明为什么上面的内容对您没有帮助。