如何等到异步任务中另一个类的方法在android中完成
Posted
技术标签:
【中文标题】如何等到异步任务中另一个类的方法在android中完成【英文标题】:How to wait until method from another class in asynctask finishes in android 【发布时间】:2018-01-06 13:27:34 【问题描述】:我是 AsyncTask 的新手,我遇到了问题。 我有 AsyncTask,它通过调用另一个类的函数将信息保存在 DB 中。问题是 onPostExecute 方法在我的函数完成之前调用;这是我的代码:
class checkNewReviews2 extends AsyncTask<List<ReviewList.ReviewItem>, Void, Void>
@Override
protected Void doInBackground(List<ReviewList.ReviewItem>... reviewList)
int size = reviewList[0].size();
if(size>0)
for (int i = 0; i < size; i++)
ReviewList.ReviewItem r = reviewList[0].get(i);
ContentValues c = new ContentValues();
c.put(LentaClass.LentaListEntry.FILM_ID, r.getFilm_id());
c.put(LentaClass.LentaListEntry.USER_ID, r.getUser_id());
c.put(LentaClass.LentaListEntry.REVIEW_TEXT, r.getReview_text());
c.put(LentaClass.LentaListEntry.CREATED_AT, r.getCreated_at());
c.put(LentaClass.LentaListEntry.REVIEW_TYPE, r.getReview_type());
c.put(LentaClass.LentaListEntry.VIEWS, r.getViews());
sqLiteDatabase.insert(LentaClass.LentaListEntry.TABLE_NAME, null, c);
c.clear();
FilmHandler filmHandler = new FilmHandler(getContext());
filmHandler.HandleFilms(reviewList[0]);
UserHandler userHandler = new UserHandler(getContext());
userHandler.HandleUsers(reviewList[0]);
return null;
@Override
protected void onPostExecute(Void result)
super.onPostExecute(result);
initiateRecyclerView();
我已经尝试将所有调用放入 onPreExecute,但结果仍然相同。另请注意,第一块 sql 代码(循环)已成功处理,而不是作为 Film 和 User 处理程序。 AsyncTask 完全执行后,我应该如何调用initialRecyclerView?
【问题讨论】:
The problem is that onPostExecute method is calling before my function finishes
可能您正在使用来自doInBackground
workThread 的其他线程
onPostExecute 将仅在 doInBackground 完成后执行。如果 FilmHandler 和 Userhandler 在单独的线程上实现,可能会导致问题。因此为避免这种情况,请不要使用另一个线程将数据保存在 DB 中,而是在 doInBackground 本身中完成整个保存数据。
那么我怎样才能在同一个线程中运行 FilmHandler 和 UserHandler 呢?
【参考方案1】:
您的doInBackgound()
方法需要“等待”您的FilmHandler
、UserHandler
类完成。
我的猜测是您的类正在后台线程上工作,因此当您使用它们时,您的代码会立即继续执行 return null
语句 - 并完成后台工作,从而导致调用 onPostExecute()
。
更改您的类实现以在调用线程上工作,而不是创建自己的。
【讨论】:
有没有例子说明如何实现调用线程的使用? 这将是非常具体的,并且超出了我在 *** 中可以解释的范围。我建议你先阅读类的源代码,看看它们使用了哪些异步技术(线程、AsyncTask 等...)。【参考方案2】:您能否也将上下文添加到 doinbackground 参数。可能是 getcontext 返回 null/应用程序上下文
【讨论】:
【参考方案3】:onPostExecute 只会在 doInBackground 完成后执行。如果 FilmHandler 和 Userhandler 在单独的线程上实现,则可能会导致问题。所以为避免这种情况,不要使用另一个线程将数据保存在 DB 中(或)执行一些其他类型的操作,而是在 doInBackground 本身中完成整个保存数据。
还有另一种方法可以存档功能。您需要为 filmHandler 或 userHandler 函数添加回调并检查 doinBackground 中的更新,并基于它您可以将结果传递给 PostExcecute()
class checkNewReviews2 extends AsyncTask<List<ReviewList.ReviewItem>, Void, Boolean>
@Override
protected Void doInBackground(List<ReviewList.ReviewItem>... reviewList)
int size = reviewList[0].size();
if(size>0)
for (int i = 0; i < size; i++)
ReviewList.ReviewItem r = reviewList[0].get(i);
ContentValues c = new ContentValues();
c.put(LentaClass.LentaListEntry.FILM_ID, r.getFilm_id());
c.put(LentaClass.LentaListEntry.USER_ID, r.getUser_id());
c.put(LentaClass.LentaListEntry.REVIEW_TEXT, r.getReview_text());
c.put(LentaClass.LentaListEntry.CREATED_AT, r.getCreated_at());
c.put(LentaClass.LentaListEntry.REVIEW_TYPE, r.getReview_type());
c.put(LentaClass.LentaListEntry.VIEWS, r.getViews());
sqLiteDatabase.insert(LentaClass.LentaListEntry.TABLE_NAME, null, c);
c.clear();
FilmHandler filmHandler = new FilmHandler(YourActivity.this);
boolean filmHandlerState = filmHandler.HandleFilms(reviewList[0]);
UserHandler userHandler = new UserHandler(YourActivity.this);
boolean userHandlerState = userHandler.HandleUsers(reviewList[0]);
if(filmHandlerState && userHandlerState )
return true;
else
return false;
@Override
protected void onPostExecute(Void result)
super.onPostExecute(result);
if(result)
initiateRecyclerView();
else
// any one of the filmHandler or userHandler function has failed. so do your handling here
@user3413619 所述的另一点可能是 getContext() 返回 null 所以,尝试将其设为 YourActivity.this
【讨论】:
我忘了补充,这段代码在Fragment中,所以我不能使用Activity.this 那么你必须添加getActivity()而不是getContext()。用你的旧代码试试这个 我按你说的改了,但问题依旧 我试过了,但是它失败了,因为我的Handlers没有返回任何值,所以我尝试在Handlers中创建新的AsyncTask以获得任何结果并返回给Fragment,但是这个新的AsyncTask失败了T_T。跨度> 【参考方案4】:使 doInBackground 方法返回 boolean 类型并将结果传递给 postExecute boolean 然后检查结果是否为 true 执行您要调用的方法。
谢谢
【讨论】:
以上是关于如何等到异步任务中另一个类的方法在android中完成的主要内容,如果未能解决你的问题,请参考以下文章