代码之家  ›  专栏  ›  技术社区  ›  obrassard

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

  •  2
  • obrassard  · 技术社区  · 7 年前

    我正在使用Room数据持久性库制作一个Android应用程序,但是我很难想出如何在新线程中查询数据库并将值返回到主线程。。。

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

    @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 回复  |  直到 7 年前
        1
  •  2
  •   MarGin    7 年前

    此代码似乎存在问题:

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

    然后它应该会起作用。

    作为补充说明,您应该使用异步任务而不是线程,因为AsyncTask设计用于android线程模型,允许您在单独线程上工作时轻松跟踪进度。

        2
  •  1
  •   Pauliman    6 年前

    这是一个使用AsyncTask的示例。由于在不同线程中实际运行的唯一方法是“doInBackground()”,因此很容易将数据写回UI线程。AsyncTask类签名的第一个参数定义了'doInBackground(Param Param)'-方法的参数类型。这里可以传递对调用类/活动的引用,该类/活动是您的UI线程。让任务执行您希望它执行的操作,并将结果返回给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
    

    您还可以将所有内容压缩到一个嵌套类或侦听器中,并保存传递上下文的过程。