1

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

问题是,该海报没有收藏视图,只有一个项目。当我尝试遵循该模式时,每次 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;
}
4

2 回答 2

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();
}
于 2013-08-18T23:51:34.673 回答
0

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

于 2013-08-10T23:06:21.083 回答