当前位置: 首页 > 知识库问答 >
问题:

如何从DAO查询返回单个int值?

宗烨赫
2023-03-14

我在DAO文件中返回查询时遇到问题。我想在MainActivity中存储一个变量,用于插入的最后一个ID:

int lastId = taskViewModel.getLastID();

在DAO中,我有以下查询:

@Query ("SELECT MAX(id) FROM task_table")
int getLastID();
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;
     }
    }
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的通知。我该怎么做呢?

MainActivity、TaskViewModel、TaskRepository、TaskDao

共有1个答案

司马晋
2023-03-14

您的错误是因为您正在将dao访问到主线程“导致:java.lang.IllegalStateException:无法访问主线程上的数据库,因为它可能会在很长一段时间内锁定UI。”

更改为在后台任务或livedata中运行

在后台运行任务示例

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) {

            }
        });

    }
 } 
        //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();
        }
    }

使用calback调用

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);
 类似资料:
  • 问题内容: 基本上,我想要Android中的EditText,可以在其中输入一个整数值。也许有比EditText更合适的对象了吗? 问题答案: 现在,使用。使用强制它是数字。将结果字符串转换为整数(例如)。 将来,您可能会考虑使用可用的小部件(计划在Honeycomb中使用)。

  • 问题内容: 一个简单的问题:如何返回MySQL表的字段类型。我知道还是但是我只想返回那个单个参数。例如: 问题答案: 您可以使用 这将以以下格式返回结果

  • 问题内容: 以下查询应返回从动漫中扮演角色的人物的姓名。但我收到以下错误: Blockquote ORA-01427:单行子查询返回多个行 提前致谢! 问题答案: 代替 使用 查询中有5个条件需要更改。 UPD 另外,您的查询等同于

  • 问题内容: 我正在尝试获取少量数据,在Excel中包含大约200个字段,并从SQL中检索数据,其中每个项目的where子句中都包含该字段。 我希望能够在excel中进行检索(希望本身无需编写任何其他代码-可能是简单的Excel ODBC或带有查询的SQL连接。因此,我的数据最终将在Excel文档中显示: 我不确定我是否足够清楚地说明自己…。 我使用的是Excel 2007,而我在其他地方也有201

  • 问题内容: 我想知道以下内容: 如何从数据库中的多个表中获取数据? 有哪些类型的方法可以做到这一点? 什么是联接和工会,它们之间有何不同? 什么时候应该使用每个与其他比较? 我打算在我的应用程序(例如,PHP)中使用此功能,但是不想对数据库运行多个查询,我需要在单个查询中从多个表中获取数据的哪些选项? 注意:我正在写这篇文章是因为我希望能够链接到有关我在PHP队列中不断遇到的众多问题的书面指南,因

  • 问题内容: 桌子: 我的查询: 我收到“ MySQL子查询返回多个行”错误。 我知道此查询可以使用以下查询的解决方法: 然后使用php循环遍历结果并执行以下查询以获取和回显它: 但是我认为可能会有更好的解决方案? 问题答案: 简单的解决方法是在子查询中添加一个子句: 一个更好的选择(就性能而言)是使用联接: