未调用 AsyncTask onPostExecute

AsyncTask onPostExecute not called

我有一个带有 TextView 的简单小部件。一个TextView应该显示从网页获取的信息,我用这个来实现:

private class DownloadWebpageTask extends AsyncTask<String, Void, String> {
    @Override
    protected String doInBackground(String... urls) {

        // params comes from the execute() call: params[0] is the url.
        try {
            return downloadUrl(urls[0]);
        } catch (IOException e) {
            return getString(R.string.srv_dwn);
        }
    }
    // onPostExecute displays the results of the AsyncTask.
    @Override
    protected void onPostExecute(String result) {
        widgetText1 = result;
    }
}

DownloadWebpageTask 从 activity 调用,如下所示:

    DownloadWebpageTask downloadWebpageTask = new DownloadWebpageTask();
    Context context = this;
    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
    RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.example_appwidget);
    ComponentName thisWidget = new ComponentName(context, Widget.class);

    ConnectivityManager cm =
            (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo netInfo = cm.getActiveNetworkInfo();

    if (netInfo != null && netInfo.isConnected())
    {
        remoteViews.setViewVisibility(R.id.widgettext1, View.VISIBLE);
        netInfo = cm.getActiveNetworkInfo();
        widgetText2 = netInfo.getTypeName();

        downloadWebpageTask.execute("http://checkip.amazonaws.com/");

        remoteViews.setTextViewText(R.id.widgettext1, widgetText1);
        remoteViews.setTextViewText(R.id.widgettext2, widgetText2);
        appWidgetManager.updateAppWidget(thisWidget, remoteViews);
    }
    else
    {
        remoteViews.setTextViewText(R.id.widgettext1, widgetText1);
        remoteViews.setViewVisibility(R.id.widgettext1, View.GONE);
        remoteViews.setTextViewText(R.id.widgettext2, getString(R.string.tbl_no_connection));
        appWidgetManager.updateAppWidget(thisWidget, remoteViews);
    }

这个变量在我的 Activity class 中定义,应该显示 AsyncTask 的结果,但没有。

public String widgetText1 = "initialtext";

逐步调试显示 onPostExecute 从未被调用,TextView 中的文本仍然是 'initialtext'.

第二个 TextView 根据需要进行更新,因为它不涉及 AsyncTask

不过,包括 DownloadWebpageTask 在内的类似代码在我的主 activity 中运行良好。

您所做的只是更新一个 String 变量。您应该使用 EditTextsetText 方法进行更新。所以在 onPostExecute 中执行如下操作:

@Override
protected void onPostExecute(String result)
{
    yourEditText.setText(result);
}
AsyncTask 中的

execute() 方法在后台运行,因此当您调用它时,activity 中的代码会继续执行,因为无法知道执行需要多长时间( ) 完成方法:

downloadWebpageTask.execute("http://checkip.amazonaws.com/");

remoteViews.setTextViewText(R.id.widgettext1, widgetText1);

因此,第二行在调用 onPostExcute() 之前执行,此时 wigetText1 仍然具有 "initialtext" 值。

您应该直接从 onPostExecute() 方法更新小部件(如@Willis 所说),它保证在对页面的请求完成后它会被更新。

如果您需要使 TextView 或任何东西可见,请在 onPostExecute() 方法中执行。

但实际上,为了在主 activity 中更新您的小部件,它们必须对您的 AsyncTask 可见,将其声明为内部 class 到您的 Activity class,如下:

public class myActivity extends Activity {

//Declare the TextView as a instance variable in your activity
public TextView widgetText1;

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_splash_screen);
       //Find your widget in the layout to avoid NullPointerException    when the AsynTask try to update it.
       widgetText1 = findViewById(R.id.some_id);
    }

//Inner class myTask
private class myTask extends AsyncTask<String, Void, String>{

        @Override
        protected String doInBackground(String... urls) {
            //some code
            return result;
        }

        @Override
        protected void onPostExecute(String result) {
           widgetText1.setText(result);
        }
    }
}

请注意,通过这种方式,您必须为每个 activity 要发出网页请求的 AsyncTask 创建一个新的 AsyncTask,但这里有一个关于如何创建可重用 AsyncTask 的参考。

Extracting out your AsyncTasks into separate classes makes your code cleaner

我已经切换到 Service 而不是 Activity,但我认为在这两种情况下都可以实施解决方案。

我在服务中创建了一个方法class:

public void setIPWidget(String result)
{
    Context context = this;
    RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.example_appwidget);
    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
    ComponentName thisWidget = new ComponentName(context, Widget.class);

    remoteViews.setTextViewText(R.id.widgettext1, result);
    appWidgetManager.updateAppWidget(thisWidget, remoteViews);
}

在 onPostExecute 中,我简单地调用该方法并获得结果:

    @Override
    protected void onPostExecute(String result) {
        setIPWidget(result);
    }

比我想象的要简单。