从 AsyncTask 填充 ListView 的 Android 小部件
Posted
技术标签:
【中文标题】从 AsyncTask 填充 ListView 的 Android 小部件【英文标题】:Android Widget with ListView populated from AsyncTask 【发布时间】:2018-03-25 22:34:28 【问题描述】:我正在为我的应用程序创建一个小部件,但是当我必须填充列表视图时我被卡住了。我使用我在 WidgetDataProvider(实现 RemoteViewsService.RemoteViewsFactory)的 onCreate() 中调用的 asynctask 从我的 web db 中获取每个项目。 问题是,通常当我创建小部件时,它不会填充列表,我必须等待几秒钟才能在主屏幕中释放小部件。
如果我抓住并释放小部件,它会如下所示:empty widget
如果我等待,它会像这样显示:right widget
这是我的代码:
AppWidget
public class AppWidget extends AppWidgetProvider
static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId)
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.app_widget);
Intent intent = new Intent(context, LoginActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
views.setOnClickPendingIntent(R.id.widget_title, pendingIntent);
views.setRemoteAdapter(R.id.widget_listView, new Intent(context, WidgetService.class));
appWidgetManager.updateAppWidget(appWidgetId, views);
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
super.onUpdate(context, appWidgetManager, appWidgetIds);
for (int appWidgetId : appWidgetIds)
updateAppWidget(context, appWidgetManager, appWidgetId);
@Override
public void onEnabled(Context context)
@Override
public void onDisabled(Context context)
**WidgetService **
public class WidgetService extends RemoteViewsService
@Override
public RemoteViewsFactory onGetViewFactory(Intent intent)
return new WidgetDataRemote(this, intent);
WidgetDataRemote
public class WidgetDataRemoteimplements RemoteViewsService.RemoteViewsFactory
Context context;
Intent intent;
ArrayList<String> date = new ArrayList<>();
ArrayList<String> subj = new ArrayList<>();
ArrayList<String> type = new ArrayList<>();
ArrayList<String> comment = new ArrayList<>();
JSONParser jsonParser = new JSONParser();
ArrayList<String> subjFromDb = new ArrayList<>();
int pippo = 0;
public WidgetDataRemote(Context context, Intent intent)
this.context = context;
this.intent = intent;
@Override
public RemoteViews getViewAt(int position)
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.item_widget);
remoteViews.setTextViewText(R.id.task_data, date.get(position));
remoteViews.setTextViewText(R.id.task_subject, subj.get(position));
remoteViews.setTextViewText(R.id.task_type, type.get(position));
remoteViews.setTextViewText(R.id.task_comment, comment.get(position));
return remoteViews;
@Override
public void onCreate()
new LoadSubjects().execute();
@Override
public void onDataSetChanged()
@Override
public void onDestroy()
date.clear();
subj.clear();
type.clear();
comment.clear();
@Override
public int getCount()
return date.size();
@Override
public RemoteViews getLoadingView()
return null;
@Override
public int getViewTypeCount()
return 1;
@Override
public long getItemId(int id)
return id;
@Override
public boolean hasStableIds()
return true;
class LoadSubjects extends AsyncTask<String, String, String>
@Override
protected void onPreExecute()
super.onPreExecute();
subjFromDb.clear();
pippo = 0;
@Override
protected String doInBackground(String... args)
List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("class", User.getClasse()));
JSONArray json = jsonParser.makeHttpRequestArray(Constants.URL_LOAD_SUBJECTS, "POST", params);
try
if (!json.toString().equals("[null]"))
for (int i = 0; i < json.length(); i++)
JSONObject c = json.getJSONObject(i);
String subj = c.getString(Constants.TAG_NAME);
subjFromDb.add(subj);
else
pippo = 1;
catch (JSONException e)
e.printStackTrace();
return null;
protected void onPostExecute(String file_url)
if (pippo == 0)
new LoadTasks().execute();
class LoadTasks extends AsyncTask<String, String, String>
@Override
protected void onPreExecute()
super.onPreExecute();
pippo = 0;
@Override
protected String doInBackground(String... args)
List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("id_class", User.getClasse()));
JSONArray json = jsonParser.makeHttpRequestArray(Constants.URL_LOAD_TASKS, "POST", params);
try
if (!json.toString().equals("[null]"))
for (int i = 0; i < json.length(); i++)
JSONObject c = json.getJSONObject(i);
Date data = null;
try
data = new SimpleDateFormat("yyyy-MM-dd").parse(c.getString(Constants.TAG_DATE));
catch (ParseException e)
e.printStackTrace();
String newDate = new SimpleDateFormat("dd/MM/yyyy").format(data);
if (subjFromDb.contains(c.getString(Constants.TAG_SUBJECT)))
date.add(newDate);
subj.add(c.getString(Constants.TAG_SUBJECT));
type.add(c.getString(Constants.TAG_TYPE));
comment.add(c.getString(Constants.TAG_COMMENT));
else
pippo = 1;
catch (JSONException e)
e.printStackTrace();
return null;
protected void onPostExecute(String file_url)
if (pippo == 0)
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
ComponentName thisWidget = new ComponentName(context, WidgetDataProvider.class);
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.widget_listView);
// I use this to update the listview after fetch data. Is it correct?
【问题讨论】:
【参考方案1】:我仅使用 TimerTask 并在 onPostExecute 中修改更新过程就解决了我的问题。这是我更改的文件:
WidgetDataRemote
public class WidgetDataRemote implements RemoteViewsService.RemoteViewsFactory
final Context context;
Intent intent;
ArrayList<String> date = new ArrayList<>();
ArrayList<String> subj = new ArrayList<>();
ArrayList<String> type = new ArrayList<>();
ArrayList<String> comment = new ArrayList<>();
JSONParser jsonParser = new JSONParser();
ArrayList<String> subjFromDb = new ArrayList<>();
final Context sad;
int pippo = 0;
public WidgetDataRemote(Context context, Intent intent)
this.context = context;
this.intent = intent;
sad = context;
final Handler handler = new Handler();
Timer timer = new Timer();
TimerTask doAsynchronousTask = new TimerTask()
@Override
public void run()
handler.post(new Runnable()
public void run()
try
new LoadSubjects().execute();
catch (Exception ignored)
);
;
timer.schedule(doAsynchronousTask, 0, 60000);
@Override
public RemoteViews getViewAt(int position)
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.item_widget);
if(date.size()>0)
remoteViews.setTextViewText(R.id.task_data, date.get(position));
remoteViews.setTextViewText(R.id.task_subject, subj.get(position));
remoteViews.setTextViewText(R.id.task_type, type.get(position));
remoteViews.setTextViewText(R.id.task_comment, comment.get(position));
else
remoteViews.setTextViewText(R.id.task_data, "");
remoteViews.setTextViewText(R.id.task_subject, "loading");
remoteViews.setTextViewText(R.id.task_type, "");
remoteViews.setTextViewText(R.id.task_comment, "");
return remoteViews;
@Override
public void onCreate()
Toast.makeText(context, "Loading...", Toast.LENGTH_LONG).show();
@Override
public void onDataSetChanged()
@Override
public void onDestroy()
date.clear();
subj.clear();
type.clear();
comment.clear();
@Override
public int getCount()
return date.size();
@Override
public RemoteViews getLoadingView()
return null;
@Override
public int getViewTypeCount()
return 1;
@Override
public long getItemId(int id)
return id;
@Override
public boolean hasStableIds()
return true;
class LoadSubjects extends AsyncTask<String, String, String>
@Override
protected void onPreExecute()
super.onPreExecute();
subjFromDb.clear();
pippo = 0;
@Override
protected String doInBackground(String... args)
List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("class", User.getClasse()));
JSONArray json = jsonParser.makeHttpRequestArray(Constants.URL_LOAD_SUBJECTS, "POST", params);
try
if (!json.toString().equals("[null]"))
for (int i = 0; i < json.length(); i++)
JSONObject c = json.getJSONObject(i);
String subj = c.getString(Constants.TAG_NAME);
subjFromDb.add(subj);
else
pippo = 1;
catch (JSONException e)
e.printStackTrace();
return null;
protected void onPostExecute(String file_url)
if (pippo == 0)
new LoadTasks().execute();
class LoadTasks extends AsyncTask<String, String, String>
@Override
protected void onPreExecute()
super.onPreExecute();
date.clear();
subj.clear();
type.clear();
comment.clear();
pippo = 0;
@Override
protected String doInBackground(String... args)
List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("id_class", User.getClasse()));
JSONArray json = jsonParser.makeHttpRequestArray(Constants.URL_LOAD_TASKS, "POST", params);
try
if (!json.toString().equals("[null]"))
for (int i = 0; i < json.length(); i++)
JSONObject c = json.getJSONObject(i);
Date data = null;
try
data = new SimpleDateFormat("yyyy-MM-dd").parse(c.getString(Constants.TAG_DATE));
catch (ParseException e)
e.printStackTrace();
String newDate = new SimpleDateFormat("dd/MM/yyyy").format(data);
if (subjFromDb.contains(c.getString(Constants.TAG_SUBJECT)))
date.add(newDate);
subj.add(c.getString(Constants.TAG_SUBJECT));
type.add(c.getString(Constants.TAG_TYPE));
comment.add(c.getString(Constants.TAG_COMMENT));
else
pippo = 1;
catch (JSONException e)
e.printStackTrace();
return null;
protected void onPostExecute(String file_url)
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(sad);
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetManager.getAppWidgetIds(new ComponentName(sad, AppWidget.class)), R.id.widget_listView);
【讨论】:
以上是关于从 AsyncTask 填充 ListView 的 Android 小部件的主要内容,如果未能解决你的问题,请参考以下文章
从两个不同的 AsyncTask 更新一个 ListView
从 Asynctask 更新 MainActivity 上的 ListView