bugfix> android > 投稿

医学エンティティがRoom APIを使用してデータベースに保存される、医学のリマインダーアプリを作成します。アプリの流れは次のようになります。

1)DrawerLayoutを持つアクティビティ。したがって、DrawerのNavigationViewと、ToolbarおよびFragmentのLinearViewで構成されます。

2)フラグメント#1(TopFragment-ListFragment)-2つのオプションがあります。最初のアイテムをクリックすると、2番目のフラグメント-MedicineListFragmentに移動します。

3)MedicineListFragmentはdbからすべての薬を取得し、RecyclerViewを使用して表示します-動作します。

4)アイテム(リサイクラービューのアイテム)をクリックすると、新しいアクティビティMedicineDetailsActivityを作成するインテントが作成されます。選択したアイテムのメディシンIDはRecylcerViewAdapter実装のインテントに渡されます。

@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からObserverをサブスクライブすると、1つの薬ではなく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);
}

}

そして、それがMedicalDetailsActivityです

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を意図することができます(2番目の方法で試しました-動作します)が、前述の方法を使用してこれを行いたいです。 助けてください!

回答 1 件
  • 問題は解決しました。ありがとう@pskink

    in memory database にデータを追加する前に、Room APIに関するチュートリアル(https://codelabs.developers.google.com/codelabs/android-persistence/#0)に従ってください 、 MedicineViewModel を初期化するたびに 、データベースにテストデータを入力しました。しかし、その直前に、 delete  データベースのメソッドが実行されました。

    非同期操作のため、MedicineDetailsActivityが作成されたとき、データベースはまだ作成されていませんでした。

    delete を削除した後   populate のメソッド  薬の記録が追加された方法、すべてが正常に動作します。

あなたの答え