未调用 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
变量。您应该使用 EditText
的 setText
方法进行更新。所以在 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);
}
比我想象的要简单。
我有一个带有 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
变量。您应该使用 EditText
的 setText
方法进行更新。所以在 onPostExecute
中执行如下操作:
@Override
protected void onPostExecute(String result)
{
yourEditText.setText(result);
}
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);
}
比我想象的要简单。