我在DAO文件中返回查询时遇到问题。我想在MainActivity中为最后插入的ID存储一个变量:
int lastId = taskViewModel.getLastID();
在 DAO 中,我有以下查询:
@Query ("SELECT MAX(id) FROM task_table")
int getLastID();
在 ViewModel 中,我有:
public class TaskViewModel extends AndroidViewModel {
private TaskRepository repository;
private int lastID;
public TaskViewModel(@NonNull Application application) {
super(application);
repository = new TaskRepository(application);
lastID = repository.getLastID();
}
public int getLastID(){
return lastID;
}
}
在存储库中,我有:
public class TaskRepository {
private TaskDao taskDao;
private int lastID;
public TaskRepository(Application application) {
TaskDatabase database = TaskDatabase.getInstance(application);
taskDao = database.taskDao();
lastID = taskDao.getLastID();
}
public int getLastID() {
return lastID;
}
}
因此,查询应该从表中返回单个int Id,但是在运行应用程序时出现错误,如下所示:
2019-12-03 15:37:51.096 19684-19684/com.example.todoapp E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.todoapp, PID: 19684
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.todoapp/com.example.todoapp.MainActivity}: java.lang.RuntimeException: Cannot create an instance of class com.example.todoapp.TaskViewModel
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2817)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Caused by: java.lang.RuntimeException: Cannot create an instance of class com.example.todoapp.TaskViewModel
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:238)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:164)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:130)
at com.example.todoapp.MainActivity.onCreate(MainActivity.java:60)
at android.app.Activity.performCreate(Activity.java:6975)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1213)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2770)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:334)
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:230)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:164)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:130)
at com.example.todoapp.MainActivity.onCreate(MainActivity.java:60)
at android.app.Activity.performCreate(Activity.java:6975)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1213)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2770)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Caused by: java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
at androidx.room.RoomDatabase.assertNotMainThread(RoomDatabase.java:267)
at androidx.room.RoomDatabase.query(RoomDatabase.java:323)
at androidx.room.util.DBUtil.query(DBUtil.java:83)
at com.example.todoapp.TaskDao_Impl.getLastID(TaskDao_Impl.java:1794)
at com.example.todoapp.TaskRepository.<init>(TaskRepository.java:94)
at com.example.todoapp.TaskViewModel.<init>(TaskViewModel.java:59)
at java.lang.reflect.Constructor.newInstance0(Native Method)
at java.lang.reflect.Constructor.newInstance(Constructor.java:334)
at androidx.lifecycle.ViewModelProvider$AndroidViewModelFactory.create(ViewModelProvider.java:230)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:164)
at androidx.lifecycle.ViewModelProvider.get(ViewModelProvider.java:130)
at com.example.todoapp.MainActivity.onCreate(MainActivity.java:60)
at android.app.Activity.performCreate(Activity.java:6975)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1213)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2770)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
我认为查询的返回类型或如何读取返回类型有问题。 有人可以帮我吗? 预先谢谢你
小步骤
使用LiveData,我实际上可以看到我插入的任务的ID是什么,但是我无法在onChange方法之外使用它。 我需要此ID,因为我想创建ID ==到任务ID的通知。我该怎么办?
更新和问题 如果我在主要活动中设置了这样的变量:'private int lastID;'并且我在onChange方法中使用它(使用LiveData模式),无法在该方法之外使用它,因为我收到错误“ NullPointException”(请参见下面的答案)。我确实需要一种方法来简单地保存插入的Task的ID,然后将其用于创建Notification。我不知道该怎么办.....
这里有我的主要文件
答案 0 :(得分:2)
您的错误是因为您正在访问主线程“引起原因:java.lang.IllegalStateException:无法访问主线程上的数据库,因为它可能会长时间锁定UI。”
更改为在后台任务或实时数据中运行
在下面的后台任务示例中运行
public class TaskRepository {
private TaskDao taskDao;
private int lastID;
public TaskRepository(Application application) {
TaskDatabase database = TaskDatabase.getInstance(application);
taskDao = database.taskDao();
//run in backgroung task
Executors.newSingleThreadExecutor().execute(new Runnable() {
@Override
public void run() {
lastID = repository.getLastID();
}
});
}
public int getLastID() {
return lastID;
}
}
使用实时数据示例运行
@Query ("SELECT MAX(id) FROM task_table")
LiveData<int> getLastID();
public class TaskViewModel extends AndroidViewModel {
private TaskRepository repository;
private int lastID;
public TaskViewModel(@NonNull Application application) {
super(application);
repository = new TaskRepository(application);
}
public LiveData<int> getLastID() {
return taskDao.getLastID();
}
}
public class TaskRepository {
private TaskDao taskDao;
private int lastID;
public TaskRepository(Application application) {
TaskDatabase database = TaskDatabase.getInstance(application);
taskDao = database.taskDao();
}
public LiveData<int> getLastID() {
return taskDao.getLastID();
}
}
public class MainActivity extends AppCompatActivity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
TaskViewModel viewmodel = new TaskViewModel(getApplicationContext())
dao.getLastID().observe(this, new Observer<int>() {
@Override
public void onChanged(int value) {
}
});
}
}
编辑任务 //根据每个操作员的编码,对DB sui踏步操作进行后台操作 公共静态类InsertTaskAsyncTask扩展了AsyncTask { // abbiamo bisogno che taskDao ci faccia Operazioni DB 私人TaskDao taskDao; 私有ResultListener onResultListener; 私人InsertTaskAsyncTask(ResultListener onResultListener,TaskDao taskDao){ this.taskDao = taskDao; this.onResultListener = onResultListener; }
//unico metodo obbligatorio
@Override
protected Void doInBackground(Task... tasks) {
taskDao.insert(tasks[0]);
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
if (onResultListener != null) {
onResultListener.onResult();
}
}
interface ResultListener{
public void onResult();
}
}
致电使用回拨
taskViewModel.insert(new TaskRepository.InsertTaskAsyncTask.ResultListener(){
@Override
public void onResult() {
Task task = new Task(title, data_calendario, time, priority, type, note, "pending");
taskViewModel.insert(new TaskRepository.InsertTaskAsyncTask.ResultListener(){
@Override
public void onResult() {
taskViewModel.getLastID().observe(MainActivity.this, new Observer<Integer>() {
@Override
public void onChanged(Integer integer) {
System.out.println("Test ID: "+integer);
}
});
}
}, task);