如何等到异步任务中另一个类的方法在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() 方法需要“等待”您的FilmHandlerUserHandler 类完成。

我的猜测是您的类正在后台线程上工作,因此当您使用它们时,您的代码会立即继续执行 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中完成的主要内容,如果未能解决你的问题,请参考以下文章

作为 Flutter 中另一个类的参数的类列表

Java并发编程核心概念一览

如何在android中停止异步任务线程?

如何将异步任务结果传递给另一个活动?

在android中链接2个异步任务的正确方法

我如何知道取消的异步任务是不是完成?