使用AsyncTask将图像下载到AppWidget中的ListView中

时间:2013-08-10 22:54:56

标签: android android-appwidget remoteview

我正在尝试使用AsyncTask从Google I/O调整模式以从网络下载图像并将它们放入AppWidget中的ListView项目中。除了this post之外,我没有找到很多资源来做这样的事情。

问题是,海报没有集合视图,只有一个项目。当我尝试遵循该模式时,每次onPostExecute()运行时,整个appwidget仅使用单个列表项进行更新,而不是我需要的。如果在onPostExecute()中删除对updateAppWidget()的调用,则不会更新视图,我猜是因为必须发生进程间通信。我不确定从哪里开始,有人可以帮忙吗?

这是我对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;
}
}

和RemoteViewsFactory中的getViewAt():

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 个答案:

答案 0 :(得分:1)

我对加载时间过长感到不满意,所以我找到了一种方法来快速加载占位符图像,然后在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();
}

答案 1 :(得分:0)

我相信您需要调用AppWidgetManager.notifyAppWidgetViewDataChanged()来刷新AppWidget中的集合视图