【问题标题】:Room Database Query房间数据库查询
【发布时间】:2018-09-09 09:00:06
【问题描述】:

我是Room 的新手,我正在尝试通过query 我的database 从中获取row。我尝试通过querying 使用 id 的primary key 这样做,但问题是我不知道如何从repository 返回目标object

这是Dao

@Query("SELECT * FROM targets WHERE id = :id LIMIT 1")
Targets findTargetById(int id);

这是存储库类

 public Targets findTarget (int id) {
    new findTargetByIDAsyncTask(mTargetsDao).execute(id);

}

   private static class findTargetByIDAsyncTask extends AsyncTask<Integer, Void, Targets> {

    private TargetsDao mAsyncTaskDao;

    findTargetByIDAsyncTask(TargetsDao dao) {
        mAsyncTaskDao = dao;
    }


    @Override
    protected Targets doInBackground(Integer... integers) {

        return mAsyncTaskDao.findTargetById(integers[0]);
    }

    @Override
    protected void onPostExecute(Targets targets) {
        super.onPostExecute(targets);
    }
}

【问题讨论】:

  • 您可以在存储库的 onPostExecute 方法中对目标执行任何操作。如果您想在 assyncTask 之外的任何地方使用它,那么您可以创建一个全局变量并影响 onPostExecute 中的值

标签: java android android-room


【解决方案1】:

您有两种方法可以返回结果。

第一种方法是调用AsyncTask.get() 方法,但是如果任务超过5秒,它仍然会持有一个导致ANR的MainThread:

public Targets findTarget (int id) {
    return new findTargetByIDAsyncTask(mTargetsDao).execute(id).get();
}

第二种方法更复杂,但它不会持有 MainThread。你应该添加一个回调类:

public interface Callback {
        void onSuccess(Targets targets);
    }

您的存储库的每个方法都将如下所示:

public void findTarget (Callback callback, int id) {
        new findTargetByIDAsyncTask(mTargetsDao, callback).execute(id);
    }

AsynTask 看起来像这样:

private static class FindTargetByIDAsyncTask extends AsyncTask<Integer, Void, Targets> {

    private final TargetsDao mAsyncTaskDao;
    private final Callback callback;

    FindTargetByIDAsyncTask(TargetsDao dao, Callback callback) {
        mAsyncTaskDao = dao;
        this.callback = callback;
    }


    @Override
    protected Targets doInBackground(Integer... integers) {
        return mAsyncTaskDao.findTargetById(integers[0]);
    }

    @Override
    protected void onPostExecute(Targets targets) {
        callback.onSuccess(targets);
    }
}

【讨论】:

    【解决方案2】:

    关键是从后台线程获取数据/对象。您可以使用 Android 的 AsyncTaskExecutorService。一个简单的例子是,如果你想得到一个用户名的字符串,方法将是:

    private String getName() {
        String name = null;
        try {
            name = Executors.newSingleThreadExecutor().submit(() ->
                    userDao.fetchUserName()).get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
        return name;
    }
    

    【讨论】:

    • 我有一个类似的用例。您的答案看起来简单而有效。但我看到很多使用 Callable 和 Future 返回对象的答案(参见stackoverflow.com/questions/40658145/…)。非常感谢您对您的方法与 Callable/Future 方法的看法。
    猜你喜欢
    • 2018-06-18
    • 1970-01-01
    • 1970-01-01
    • 2022-09-27
    • 1970-01-01
    • 1970-01-01
    • 2021-05-21
    • 2020-05-01
    • 2019-06-02
    相关资源
    最近更新 更多