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 中,并避免自己传递上下文。
我正在使用 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 中,并避免自己传递上下文。