Return Android 房间中主线程外的数据

Return data outside the main thread in Android Room

我正在使用 Room Data Persistence Library 制作一个 Android 应用程序,但是我很难弄清楚如何在新线程中查询数据库以及 return 主线程的值线程...

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

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

在另一个 class 中,我尝试了这个:

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,我不知道如何在主线程中 return 来自 getProductById 的值。但是我确定数据库配置是正确的,因为当我使用 allowMainThreadQueries()

构建数据库时,我的所有查询都在主线程中工作

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

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

因为好像没插入什么东西

非常感谢!!

问题似乎出在这段代码上:

 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 线程模型一起使用,并允许您在单独的线程上工作时轻松跟踪进度其他好处。

这是一个使用 AsyncTask 的例子。由于实际在不同线程中运行的唯一方法是 'doInBackground()',因此很容易将数据写回 UI-Thread。 AsyncTask class 签名的第一个参数定义了'doInBackground(Param param)'-方法的参数类型。在这里可以传递对调用 class/Activity 的引用,这是您的 UI-Thread。让任务做你想让它做的事,并将结果 return 传递给 onPostExecute(Result result) 方法。在这里您可以简单地调用 UI-thread 上的任何方法并传递您的数据。 通过从 UI-thread.

调用以下命令来启动整个过程
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

您也可以将所有内容压缩到一个嵌套的 class 或 Listener 中,并避免自己传递上下文。