Использование AsyncTask для загрузки изображений в ListView в AppWidget
Я пытаюсь адаптировать шаблон из Google I/O, используя AsyncTask для загрузки изображений из сети и размещения их в элементах ListView в AppWidget. Я не нашел много ресурсов на такие вещи, кроме этого поста.
Проблема в том, что у постера не было представления коллекции, только один элемент. Когда я пытаюсь следовать этому шаблону, весь appwidget обновляется только одним элементом списка каждый раз, когда запускается onPostExecute(), а не тем, что мне нужно. Если вы удалите вызов updateAppWidget() в onPostExecute(), представления не будут обновлены, я полагаю, из-за межпроцессного взаимодействия, которое должно произойти. Я не совсем уверен, куда идти отсюда, кто-нибудь может помочь?
Вот мое определение AsyncTask:
public ThumbnailAsyncTask(RemoteViews rv, int appWidgetID, AppWidgetManager appWidgetManager)
{
mTarget = rv;
this.widgetID = appWidgetID;
this.widgetManager = appWidgetManager;
}
@Override
protected Bitmap doInBackground(String... params)
{
String url = params[0];
return getBitmapFromURL(url);
}
@Override
protected void onPostExecute(Bitmap result)
{
mTarget.setImageViewBitmap(R.id.thumbnail, result);
widgetManager.updateAppWidget(widgetID, mTarget);
}
private Bitmap getBitmapFromURL(String str)
{
Bitmap bmp = null;
HttpURLConnection connection = null;
try
{
URL url = new URL(str);
connection = openConnectionWithTimeout(url);
bmp = BitmapFactory.decodeStream(connection.getInputStream());
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
connection.disconnect();
}
return bmp;
}
}
и getViewAt() из RemoteViewsFactory:
public RemoteViews getViewAt(int position)
{
RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.list_item);
ArrayList<ResultDetails> mResults = mJSONParser.getResults();
if (mResults.get(position).hasHeading())
rv.setTextViewText(R.id.title, mResults.get(position).getHeading());
if (mResults.get(position).hasBody())
rv.setTextViewText(R.id.description, mResults.get(position).getBody(true));
if (mResults.get(position).hasTimestamp())
rv.setTextViewText(R.id.date, mResults.get(position).getTimestamp(true));
Bundle extras = new Bundle();
extras.putString(LINK_ITEM, mResults.get(position).getExternalURL());
Intent fillInIntent = new Intent();
fillInIntent.putExtras(extras);
rv.setOnClickFillInIntent(R.id.list_item, fillInIntent);
if (mResults.get(position).hasThumbnailURL())
{
AppWidgetManager mgr = AppWidgetManager.getInstance(mContext);
new ThumbnailAsyncTask(rv, mAppWidgetId, mgr).execute(mResults.get(position).getThumbnailURL());
}
return rv;
}
2 ответа
Я не был доволен длительным временем загрузки, поэтому я нашел способ быстро загрузить изображение-заполнитель, а затем загрузить миниатюры в AsyncTask, а затем один раз вызвать notifyAppWidgetViewDataChanged(), чтобы обновить appwidget после того, как все они будут загружены. Это приводит к мгновенному появлению данных без изображений и является довольно хорошим решением для моего приложения. Я использовал логическое значение в RemoteViewsFactory, чтобы указать, что я уже загрузил данные без изображений, чтобы они не застревали в бесконечном цикле обновления.
class ThumbnailAsyncTask extends AsyncTask<Void, Void, Void>
{
private AppWidgetManager widgetManager;
private List<ResultDetails> details;
private Context context;
public ThumbnailAsyncTask(AppWidgetManager
appWidgetManager, List<ResultDetails> details, Context context)
{
this.details = details;
this.context = context;
this.widgetManager = appWidgetManager;
}
@Override
protected Void doInBackground(Void... params)
{
for (ResultDetails item : details)
{
if (item.hasThumbnailURL())
{
item.setThumbnail(getBitmapFromURL(item.getThumbnailURL()));
}
}
return null;
}
@Override
protected void onPostExecute(Void result)
{
widgetManager.notifyAppWidgetViewDataChanged(widgetManager.getAppWidgetIds(
new ComponentName(context, WidgetProvider.class)), R.id.list_view);
}
public RemoteViews getViewAt(int position)
{
RemoteViews rv;
rv = new RemoteViews(mContext.getPackageName(), R.layout.list_item);
ArrayList<ResultDetails> mResults = mSearchResultsGenerator.getResults();
ResultDetails result = mResults.get(position);
if (result.hasHeading())
rv.setTextViewText(R.id.title, result.getHeading());
if (result.hasBody())
rv.setTextViewText(R.id.description, result.getBody(true));
if (result.hasTimestamp())
rv.setTextViewText(R.id.date, result.getTimestamp(true));
if (result.hasPrice())
rv.setTextViewText(R.id.price, result.getPrice());
Bundle extras = new Bundle();
extras.putString(LINK_ITEM, result.getExternalURL());
Intent fillInIntent = new Intent();
fillInIntent.putExtras(extras);
rv.setOnClickFillInIntent(R.id.list_item, fillInIntent);
if (result.hasThumbnail())
{
rv.setImageViewBitmap(R.id.thumbnail, result.getThumbnail());
}
else
{
rv.setImageViewBitmap(R.id.thumbnail, noImageBitmap);
}
return rv;
}
public void onDataSetChanged()
{
if (isOnline(mContext))
{
if (!hasData)
{
mSearchResultsGenerator.generate();
if (mSearchResultsGenerator.isUpdateSucceeded())
{
AppWidgetManager mgr = AppWidgetManager.getInstance(mContext);
hasData = true;
new ThumbnailAsyncTask(mgr, mSearchResultsGenerator.getResults(), mContext).execute();
}
else
makeNoConnectionToast();
}
else
{
}
}
else
makeNoConnectionToast();
}
Я считаю, что вам нужно позвонить AppWidgetManager.notifyAppWidgetViewDataChanged()
обновить представления коллекции в AppWidget