在Android Room中的主线程外返回数据

时间:2018-03-27 00:46:50

标签: java android multithreading persistence android-room

我正在使用房间数据持久性库创建一个Android应用程序,但是我很难弄清楚如何在新线程中查询数据库并将值返回给主线程...

例如,我的ProductDAO中有一个方法可以通过他的barCode检索一个产品:

@Query("SELECT * FROM Product WHERE barCode = :barCode")
Product getProductById (String barCode);

在另一堂课中我试过这个:

public Product getProduct(final String barcode){
    final Product[] product = new Product[1];
    new Thread(new Runnable() {
        @Override
        public void run() {
            product[0] = db.inventory().getProductById(barcode);
        }
    });
    return product[0];
}

但结果总是null,我不知道如何从主线程中的getProductById返回值。我确定数据库配置是正确的,因为当我使用allowMainThreadQueries()构建数据库时,我的所有查询都在主线程中工作

从新线程插入产品时也遇到同样的问题:

public void AddProduct(final Product product){
    new Thread(new Runnable() {
        @Override
        public void run() {
            db.inventory().insertOneProduct(product);
        }
    });
}

因为它似乎没有插入任何东西。

非常感谢!!

2 个答案:

答案 0 :(得分:2)

问题似乎与此代码有关:

 public void AddProduct(final Product product){
new Thread(new Runnable() {
    @Override
    public void run() {
        db.inventory().insertOneProduct(product);
    }
});
 }

虽然您已创建了一个线程,但您没有调用start方法。所以改成它:

 public void AddProduct(final Product product){
new Thread(new Runnable() {
    @Override
    public void run() {
        db.inventory().insertOneProduct(product);
    }
}).start();
}

然后它应该有用。

作为旁注,您应该使用Async Task而不是线程,因为AsyncTask旨在与android线程模型一起使用,并允许您在单独的线程上工作时轻松跟踪进度以及其他好处。

答案 1 :(得分:-1)

这是使用AsyncTask的示例。由于实际在不同线程中运行的唯一方法是“ doInBackground()”,因此很容易将数据写回UI-Thread。 AsyncTask类签名的第一个参数定义“ doInBackground(Param param)”方法的参数类型。在这里可以传递对调用类/活动的引用,这是您的UI-Thread。让任务做您想做的事情,然后将结果返回给onPostExecute(Result result)方法。在这里,您可以简单地在UI线程上调用任何方法并传递数据。 通过从您的UI线程中调用以下内容来启动整个过程。

new AllUsersLoader().execute(this); 

public class AllUsersLoader extends AsyncTask<Context, Void, List<User>>{
        private AppDataBase db;
        private UserDao dao;
        private List<User> users;
        private MainActivity con;

    /**
     * This method actually runs on a Non-UI-Thread.
     * @param contexts A reference to the MainActivity
     * @return Result that is passed to onPostExecute()
     */
    @Override
    protected List<User> doInBackground(Context... contexts) {

        this.con = (MainActivity) contexts[0];
        db = Room.databaseBuilder(con.getApplicationContext(), AppDataBase.class, con.getResources().getString(R.string.db_scema_name)).build();
        dao = db.getUserDao();
        users = dao.getAllUsers();
        db.close();
        return users;
    }

    /**
     * This method is again part of the UI-Thread but waits till it receives the result from doInBackground()
     * @param users
     */
    @Override
    protected void onPostExecute(List<User> users) {            
        super.onPostExecute(users);
        con.updateRecyclerView(users); //a method of the UI-thread expecting the result
    }
} // end of class

您还可以将所有内容限制在一个嵌套类或Listener中,并保存自己通过上下文的操作。