【问题标题】:How to return value only after onPostExecute() of AsyncTask executes?如何仅在 AsyncTask 的 onPostExecute() 执行后才返回值?
【发布时间】:2017-03-18 09:51:46
【问题描述】:

我试图通过从网站上抓取数据来填充 RecyclerView。问题是SearchCards.java(模型)的getData() 方法在AsyncTask 完成执行之前返回字符串(pageTitle),导致空字符串。这是我的代码

FragmentOne.java

 mAdapter = new SearchAdapter(SearchCards.getData(),this,recyclerView);
 recyclerView.setAdapter(mAdapter);

SearchCards.java

public static ArrayList<SearchCards> getData() {

    ArrayList<SearchCards> datatList = new ArrayList<SearchCards>();

    String pageTitle = new Scrapping().scrapSubs(); //scrapSubs contains AsynTask                     
    String[] yearArr = setYearArr();

    for (int i = 0; i < yearArr.length; i++) {
        SearchCards searchCard = new SearchCards();
        searchCard.setYear(yearArr[i]);
        searchCard.setTitle(pageTitle); //same pagetitle for every year
        datatList.add(searchCard);             
    }      

    return dataList;
}

Scrapping.java

public String ScrapSubs(){
    JsoupAsyncTask jsoupAsyncTask = new JsoupAsyncTask();
    jsoupAsyncTask.execute();
    return pageTitle;
}

private class JsoupAsyncTask extends AsyncTask<Void, Void, Void> {
    @Override
        protected Void doInBackground(Void... params) {
            try {
                htmlDocument = Jsoup.connect(htmlPageUrl).get();
                pageTitle = htmlDocument.title();
                Log.i(TAG,"PAGETITLE"+pageTitle);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

    @Override
        protected void onPostExecute(Void result) {
        //do something
        }
}

如何在 Scrapping.java 中执行诸如 return pageTitle 之类的操作,仅在 AsyncTask 执行完成后执行。我试过了,但没有用:

if(jsoupAsyncTask.getStatus() == AsyncTask.Status.FINISHED){
     return pageTitle;
}

编辑: 可能这不是一个经过充分研究的问题。在这里我找到了我想要的东西:http://stacktips.com/tutorials/android/android-recyclerview-example 我所要做的就是在 onPostExecute() 中移动 SearchAdapter 初始化。

【问题讨论】:

  • protected void onPostExecute(Void result) { //do something。不仅是东西。但例如调用修改后的 getData() 并设置您的列表视图。这是正常的方式。请调整您的设计。你现在拥有的根本不是要走的路。
  • 感谢您的意见。我是 android 新手,正在努力适应。虽然这里的答案让我更清楚地继续。

标签: java android android-asynctask android-recyclerview


【解决方案1】:

创建接口:

private class JsoupAsyncTask extends AsyncTask<Void, Void, Void> {

    public interface FinishListener {
        void processFinish(Boolean isFinish);
    }

    FinishListener finishListener = null;

    public JsoupAsyncTask(FinishListener  finishListener) {
        this.finishListener = finishListener;
    }

    @Override
    protected Void doInBackground(Void... params) {
        try {
            htmlDocument = Jsoup.connect(htmlPageUrl).get();
            pageTitle = htmlDocument.title();
            Log.i(TAG, "PAGETITLE" + pageTitle);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        finishListener.processFinish(true);
        //do something
    }
}

和听众:

new JsoupAsyncTask(new JsoupAsyncTask.FinishListener() {
@Override
public void processFinish(Boolean isFinish) {
        // do somthing  }
        }).execute();

【讨论】:

    【解决方案2】:

    如果你想在完成时传递doInBackground 的结果,只需定义你想在3th AsyncTask 参数类型(Integer)中传递的任何数据类型。这里我想要将整数结果传递给onPostExecute,其中显示了操作状态。 0 失败,1 成功。

    private class JsoupAsyncTask extends AsyncTask<Void, Void, Integer> {
            @Override
            protected int doInBackground(Void... params) {
                try {
                    htmlDocument = Jsoup.connect(htmlPageUrl).get();
                    pageTitle = htmlDocument.title();
                    Log.i(TAG,"PAGETITLE " + pageTitle);
                    return 1;
                } catch (IOException e) {
                    e.printStackTrace();
                    return 0;
                }
            }
    
            @Override
            protected void onPostExecute(int result){
             //TODO 
             if(result == 1){Log.i("state:","successful");}else{Log.i("state:","failed");}
            }
    }
    

    【讨论】:

      【解决方案3】:

      如果您希望您的代码同步运行,那么您根本不需要使用 AsyncTask - 只需创建一个执行您需要的方法并调用它。 然而,这在 UI 线程中不起作用 - UI 线程方法必须快速返回,否则整个应用程序会停止。 你可能不得不重新考虑你的设计。一种方法是在 AsyncTask 在后台运行时显示某种“等待 ui”、微调器、进度条等,并且仅当您有数据移动并显示它时。

      【讨论】:

      • 我尝试不使用 AsyncTask。它抛出异常。 developer.android.com/reference/android/os/…
      • 当然可以。您必须了解为什么会这样,以及为什么您的想法行不通。
      • 是的,我现在开始工作了。我之前的做法是错误的。现在我直接从我的 Fragment 类调用 AsyncTask.execute() 并在 onPostExecute() 中初始化 RecyclerView。正如你所建议的,我重新考虑了我的设计。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-19
      • 1970-01-01
      相关资源
      最近更新 更多