Android 同步异步任务
我正在使用内存数据库,做一些简单的任务,比如写一些电影,然后把它们读出来并显示出来。我正在使用RoomPersistance,我已经设置了一些存储库。我的问题是: 在这里,我从响应中获取电影,并通过insertMovie方法将它们插入数据库中Android 同步异步任务,android,multithreading,Android,Multithreading,我正在使用内存数据库,做一些简单的任务,比如写一些电影,然后把它们读出来并显示出来。我正在使用RoomPersistance,我已经设置了一些存储库。我的问题是: 在这里,我从响应中获取电影,并通过insertMovie方法将它们插入数据库中 for (OMDBItem movie : response.body().getItems()) { omdbItemRepository.ins
for (OMDBItem movie : response.body().getItems())
{
omdbItemRepository.insertMovie(movie);
}
此方法如下所示:
public void insertMovie(OMDBItem movie){
AsyncTask<Void,Void,Void> atask = new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... voids) {
movieDataBase.movieDao().insert(movie);
return null;
}
}.execute();
}
public List<OMDBItem> getAllMovies(){
new AsyncTask<Void,Void,Void>(){
@Override
protected Void doInBackground(Void... voids) {
lista_filmovi=movieDataBase.movieDao().getAllMovies();
return null;
}
}.execute();
return lista_filmovi;
}
/** ViewModel providing additional features to ease Room DB access */
public class RoomViewModel extends AndroidViewModel {
/** Thread executing Room operations */
private static class RoomThread extends Thread {
/** Queue of tasks pending execution */
private BlockingQueue<Runnable> tasks = new LinkedBlockingQueue<>();
/** Set to false to stop */
private boolean running = true;
/** Send this to stop the execution */
private Runnable STOP = new Runnable() {
@Override
public void run() {
running = false;
}
};
@Override
public void run()
{
while (running) {
try {
// execute next in line, when available
tasks.take().run();
} catch (InterruptedException e) {
// this should not happen
return;
}
}
}
}
/** Executes backround Room requests in order */
private RoomThread roomThread = new RoomThread();
public RoomViewModel(@NonNull Application application) {
super(application);
// start the background execution thread
roomThread.start();
}
/**
* Queues the specified Runnable for execution
* @param runnable The Runnable to be executed in background
*/
protected void execute(Runnable runnable)
{
roomThread.tasks.offer(runnable);
}
@Override
protected void onCleared() {
// queue the stop request
execute(roomThread.STOP);
super.onCleared();
}
}
getAllMovies是一种类似的方法,如下所示:
public void insertMovie(OMDBItem movie){
AsyncTask<Void,Void,Void> atask = new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... voids) {
movieDataBase.movieDao().insert(movie);
return null;
}
}.execute();
}
public List<OMDBItem> getAllMovies(){
new AsyncTask<Void,Void,Void>(){
@Override
protected Void doInBackground(Void... voids) {
lista_filmovi=movieDataBase.movieDao().getAllMovies();
return null;
}
}.execute();
return lista_filmovi;
}
/** ViewModel providing additional features to ease Room DB access */
public class RoomViewModel extends AndroidViewModel {
/** Thread executing Room operations */
private static class RoomThread extends Thread {
/** Queue of tasks pending execution */
private BlockingQueue<Runnable> tasks = new LinkedBlockingQueue<>();
/** Set to false to stop */
private boolean running = true;
/** Send this to stop the execution */
private Runnable STOP = new Runnable() {
@Override
public void run() {
running = false;
}
};
@Override
public void run()
{
while (running) {
try {
// execute next in line, when available
tasks.take().run();
} catch (InterruptedException e) {
// this should not happen
return;
}
}
}
}
/** Executes backround Room requests in order */
private RoomThread roomThread = new RoomThread();
public RoomViewModel(@NonNull Application application) {
super(application);
// start the background execution thread
roomThread.start();
}
/**
* Queues the specified Runnable for execution
* @param runnable The Runnable to be executed in background
*/
protected void execute(Runnable runnable)
{
roomThread.tasks.offer(runnable);
}
@Override
protected void onCleared() {
// queue the stop request
execute(roomThread.STOP);
super.onCleared();
}
}
问题是,有时候,这个方法getAllMovies会返回我想要的电影,但有时候它只返回null。它只在我放置一些断点并在调试器中运行时返回电影。我的问题是,通过在调试器中运行它并单击方法,我会给insertMoviemovie AsyncTasks更多的时间来完成它的工作,当调用getAllMovies时,它会给我一个很好的结果。所以基本上,问题是,我是否可以让getAllMovies异步任务在insertMovie异步任务完成之前不启动。我知道我可以在insertMovie中设置一个onPostExecute,但是我希望这些方法被单独创建,我不想每次在insertMovie之后调用getAllMovies。有什么解决方案吗?您的代码中有一些问题。 首先,您需要等待数据库中写入的所有电影开始读回。然后在读取过程中,不能只返回lista_filmovi的值,因为读取是异步的,所以当您尝试读取时,返回的值将不存在 编写电影的异步任务示例如下:
public static class InsertMovie extends AsyncTask<OMDBItem,Void,Void> {
private final Database movieDataBase;
public InsertMovie(Database movieDataBase) {
this.movieDataBase = movieDataBase;
}
@Override
protected Void doInBackground(OMDBItem... movies) {
for (OMDBItem movie : movies)
movieDataBase.movieDao().insert(movie);
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
// data is stored
}
}
在调用OnPostExecute之前,不得尝试读取数据。有多种方法可以做到这一点,但更简单的方法可能是从那里开始阅读
然后再读一遍:
public static class GetAllMovies extends AsyncTask<Void,Void,List<OMDBItem>> {
private final Database movieDataBase;
public GetAllMovies(Database movieDataBase) {
this.movieDataBase = movieDataBase;
}
@Override
protected List<OMDBItem> doInBackground(Void... voids) {
return movieDataBase.movieDao().getAllMovies();
}
@Override
protected void onPostExecute(List<OMDBItem> allMovies) {
// post the result to your activity
}
}
这对您很有帮助,因为您只有一个后台线程用于DB访问,因此操作将被排序
在MoviewModel扩展RoomViewModel中,您可以使用:
// write the movies
execute(new Runnable() {
@Override
public void run() {
for (OMDBItem movie : movies) movieDataBase.movieDao().insert(movie);
}
});
及
在“活动”中,您可以将allMovies作为可变LiveData进行观察,并在有新数据显示时收到通知。我建议您更改insertMovie的代码,以便它需要一组电影。然后,在AsyncTask触发器GetAllMovies的onPostExecute方法中,我不知道我是如何想到放入一个电影数组而不是一个电影的。谢谢你的建议,但是对于onPostExecute,我不想每次调用insertMovie时都调用getAllMovies。你不必每次都调用getAllMovies…只要在调用时有一个条件语句。或者在任务中添加一个接口,并在需要时在回调中触发getAllMovies。如果你不知道什么时候打电话给getAllMovies,什么时候不打电话给getAllMovies,你就很难给你更多的建议了。很好,我明白你的意思,谢谢你的帮助。我想是的。