订阅 LiveData 会导致在尝试从房间数据库获取对象后为 null



我编写了一个应用程序医学提醒,其中药物实体使用Room API存储在数据库中。应用程序的流程如下所示:

1(具有抽屉布局的活动,因此它由抽屉的导航视图和工具栏和片段的线性视图组成。

2(片段#1(TopFragment - 它是ListFragment( - 有两个选项。单击第一项应导航到第二个片段 - 医学列表片段。

3(MedicineListFragment从数据库中获取所有药物并使用RecyclerView显示它 - 它可以工作。

4(单击一个项目 - 在回收者视图的项目上 - 应该创建一个意图,创建新活动 医学详情活动.所选项的药物 ID 在 RecylcerViewAdapter 实现中传递到 Intent。

@Override
public void onBindViewHolder(@NonNull MedicineRecyclerViewAdapter.ViewHolder holder, final int position) {
final Medicine item = medicines.get(position);
holder.itemNameView.setText(item.getName());
holder.itemDescriptionView.setText(item.getDescription());
holder.itemContainer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(context, MedicineDetailsActivity.class);
intent.putExtra(MedicineDetailsActivity.EXTRA_MEDICINE, item.getId());
context.startActivity(intent);
}
});
}

5( 下一步应该是显示药物详细信息,但从 ViewModel 订阅观察者将返回 null 而不是单个药物。奇怪的是,如果我在调用.observer方法之前调试并设置断点,则返回药物!

public class MedicineViewModel extends AndroidViewModel {
private AppDatabase db;
public MedicineViewModel(Application application) {
super(application);
createDb();
}
public LiveData<List<Medicine>> findAllBooks() {
return db.medicineModel().findAllMedicine();
}
public LiveData<Medicine> findMedicineById(int id) {
return db.medicineModel().findMedicineById(id);
}
private void createDb() {
db = AppDatabase.getInMemoryDatabase(this.getApplication());
DatabaseInitializer.populateAsync(db);
}

}

这就是医学详情活动

public class MedicineDetailsActivity extends AppCompatActivity {
public static final String EXTRA_MEDICINE = "EXTRA_MEDICINE";
private MedicineViewModel medicineViewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_medicine_details);
medicineViewModel = ViewModelProviders.of(this).get(MedicineViewModel.class);
subscribeMedicine();
}
private void subscribeMedicine() {
Intent intent = getIntent();
int medicineId = intent.getExtras().getInt(EXTRA_MEDICINE);
medicineViewModel.findMedicineById(medicineId).observe(this, new Observer<Medicine>() {
@Override
public void onChanged(@NonNull Medicine medicine) {
showUI(medicine);
}
});
}
private void showUI(Medicine medicine) {
TextView medicineName = findViewById(R.id.medicine_details_name);
medicineName.setText(medicine.getName());
TextView medicineDescription = findViewById(R.id.medicine_details_description);
medicineDescription.setText(medicine.getDescription());
}

}

05-26 09:10:20.258 9482-9482/com.project.medicinereminder I/System.out: Sending WAIT chunk
05-26 09:10:21.282 9482-9489/com.project.medicinereminder I/art: Debugger is active
05-26 09:10:21.460 9482-9482/com.project.medicinereminder I/System.out: Debugger has connected waiting for debugger to settle...
05-26 09:10:21.661 9482-9482/com.project.medicinereminder I/System.out: waiting for debugger to settle...
05-26 09:10:21.863 9482-9482/com.project.medicinereminder I/System.out: waiting for debugger to settle...
05-26 09:10:22.064 9482-9482/com.project.medicinereminder I/System.out: waiting for debugger to settle...
05-26 09:10:22.265 9482-9482/com.project.medicinereminder I/System.out:  waiting for debugger to settle...
05-26 09:10:22.465 9482-9482/com.project.medicinereminder I/System.out: waiting for debugger to settle...
05-26 09:10:22.666 9482-9482/com.project.medicinereminder I/System.out:waiting for debugger to settle...
05-26 09:10:22.866 9482-9482/com.project.medicinereminder I/System.out: debugger has settled (1492)
05-26 09:10:23.395 9482-9482/com.project.medicinereminder W/System: ClassLoader referenced unknown path: /data/app/com.project.medicinereminder-1/lib/arm64
05-26 09:10:23.416 9482-9482/com.project.medicinereminder I/InstantRun: starting instant run server: is main process
05-26 09:10:23.463 9482-9482/com.project.medicinereminder I/HwCust: Constructor found for class android.app.HwCustActivityImpl
05-26 09:10:23.524 9482-9482/com.project.medicinereminder W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable
05-26 09:10:23.826 9482-9482/com.project.medicinereminder I/HwSecImmHelper: mSecurityInputMethodService is null
05-26 09:10:23.832 9482-9482/com.project.medicinereminder I/HwPointEventFilter: do not support AFT because of no config
05-26 09:10:23.892 9482-9511/com.project.medicinereminder I/OpenGLRenderer: Initialized EGL, version 1.4
05-26 09:10:23.902 9482-9511/com.project.medicinereminder W/linker: /vendor/lib64/libhwuibp.so: unused DT entry: type 0xf arg 0xe3a
05-26 09:10:24.002 9482-9482/com.project.medicinereminder W/art: Before Android 4.1, method int android.support.v7.widget.DropDownListView.lookForSelectablePosition(int, boolean) would have incorrectly overridden the package-private method in android.widget.ListView
05-26 09:10:24.253 9482-9487/com.project.medicinereminder I/art: Do partial code cache collection, code=29KB, data=29KB
05-26 09:10:24.254 9482-9487/com.project.medicinereminder I/art: After code cache collection, code=29KB, data=29KB Increasing code cache capacity to 128KB
05-26 09:10:33.236 9482-9482/com.project.medicinereminder I/hwaps: JNI_OnLoad
05-26 09:10:33.559 9482-9487/com.project.medicinereminder I/art: Do partial code cache collection, code=51KB, data=56KB
05-26 09:10:33.560 9482-9487/com.project.medicinereminder I/art: After code cache collection, code=50KB, data=55KB Increasing code cache capacity to 256KB
05-26 09:10:33.750 9482-9487/com.project.medicinereminder I/art: Compiler allocated 7MB to compile void android.widget.TextView.<init> (android.content.Context, android.util.AttributeSet, int, int)
05-26 09:10:47.687 9482-9489/com.project.medicinereminder I/art: Starting a blocking GC Instrumentation
05-26 09:10:47.728 9482-9487/com.project.medicinereminder I/art: Do full code cache collection, code=123KB, data=118KB
05-26 09:10:47.729 9482-9487/com.project.medicinereminder I/art: After code cache collection, code=120KB, data=92KB
05-26 09:10:47.783 9482-9482/com.project.medicinereminder I/HwPointEventFilter: do not support AFT because of no config
05-26 09:10:49.733 9482-9482/com.project.medicinereminder E/AndroidRuntime: 
FATAL EXCEPTION: main
Process: com.project.medicinereminder, PID: 9482
java.lang.NullPointerException: Attempt to read from field 'java.lang.String com.project.medicinereminder.database.Medicine.name' on a null object reference
at com.project.medicinereminder.MedicineDetailsActivity.showUI(MedicineDetailsActivity.java:44)
at com.project.medicinereminder.MedicineDetailsActivity.access$000(MedicineDetailsActivity.java:16)
at com.project.medicinereminder.MedicineDetailsActivity$1.onChanged(MedicineDetailsActivity.java:37)
at com.project.medicinereminder.MedicineDetailsActivity$1.onChanged(MedicineDetailsActivity.java:34)
at android.arch.lifecycle.LiveData.considerNotify(LiveData.java:109)
at android.arch.lifecycle.LiveData.dispatchingValue(LiveData.java:126)
at android.arch.lifecycle.LiveData.setValue(LiveData.java:282)
at android.arch.lifecycle.LiveData$1.run(LiveData.java:87)
at android.os.Handler.handleCallback(Handler.java:761)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:156)
at android.app.ActivityThread.main(ActivityThread.java:6623)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:942)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:832)
05-26 09:10:49.749 9482-9482/com.project.medicinereminder I/Process: Sending signal. PID: 9482 SIG: 9

我当然可以将 Parcerable 或 Serializable 放在意图上(我尝试了第二个 - 它有效(,但我想使用上述方式执行此操作。 请帮忙!

问题解决了。谢谢@pskink

在将数据添加到in memory database之前,按照有关Room API (https://codelabs.developers.google.com/codelabs/android-persistence/#0(的教程,每次初始化MedicineViewModel时,我都会用测试数据填充数据库。但就在它之前,delete数据库上执行了方法。

由于异步操作,创建MedicineDetailsActivity时尚未填充数据库。

从添加医学记录的方法中删除delete方法populate后,一切正常。

相关内容

  • 没有找到相关文章

最新更新