我有一个带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
,如下所示:
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
类中定义,应显示AsyncTask
的结果,但不显示。
public String widgetText1 = "initialtext";
逐步调试表明,onPostExecute
永远不会被调用,TextView
中的文字仍然是'initialtext'。
第二次TextView
根据需要进行更新,因为它不涉及AsyncTask
。
包括DownloadWebpageTask
在内的类似代码在我的主要活动中运行良好。
答案 0 :(得分:0)
您所做的只是更新String
变量。您应该使用setText
EditText
方法进行更新。所以在onPostExecute
中执行以下操作:
@Override
protected void onPostExecute(String result)
{
yourEditText.setText(result);
}
答案 1 :(得分:0)
execute()方法在后台运行,所以当你调用它时,你的活动中的代码会继续执行,因为无法知道execute()方法需要多长时间才能完成: / p>
downloadWebpageTask.execute("http://checkip.amazonaws.com/");
remoteViews.setTextViewText(R.id.widgettext1, widgetText1);
所以,第二行是在调用onPostExcute()之前执行的,此时,wigetText1仍然是&#34; initialtext&#34;值。
你应该直接从onPostExecute()方法更新小部件(如@Willis所说),它保证在页面请求完成后更新它。
如果您需要使TextView或其他任何内容可见,请在onPostExecute()方法中执行。
但实际上,为了更新主要活动中的小部件,它们必须对AsyncTask可见,并将其声明为Activity类的内部类,如下所示:
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);
}
}
}
请注意,这样,您必须为要创建网页请求的每个活动创建一个新的AsynTask,但这里有一个关于如何创建可重用AsyncTask的参考。
Extracting out your AsyncTasks into separate classes makes your code cleaner
答案 2 :(得分:0)
我已切换到Service
而不是Activity
,但我认为可以在两种情况下实施解决方案。
我在Service类中创建了一个方法:
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);
}
比我想象的要简单。