【发布时间】:2013-08-10 16:54:27
【问题描述】:
我目前在加载异步图像以填充“无限”列表视图(从 url 加载数据并存储在自定义适配器中)时遇到了一些麻烦。我找到了 ImageView 的 this 扩展方法,基本上是 koush/UrlImageViewHelper 的端口,但原来的更新很多,而且端口现在没有更新 9 个月...当我在我的自定义中填充 ImageView适配器,一切似乎都运行良好且快速(我正在从非常快的服务器下载小图像),但是在大约 200 个图像(每个 15-20 kb 大小)之后,下载停止。我认为问题出在图像缓存中,但即使使用扩展中提供的“清理”方法,也没有任何改变。有谁知道如何解决这个问题,或者对该任务有更好的解决方案?我试图创建自己的“队列”,但它有另一种问题 - 滚动列表视图时,任何新的 ImageView 已经有源图像,更改为正确的图像,但是快速滚动看起来非常糟糕。 这是我的代码:
GetView 在我的自定义列表适配器中
public override View GetView(int position, View convertView, ViewGroup parent)
{
//Populating the adapter with new items
if (position >= this._items.Count - 1)
ThreadPool.QueueUserWorkItem(o => this.LoadPage());
var item = this._items[position];
View view = convertView;
if (view == null)
view = this._context.LayoutInflater.Inflate(Resource.Layout.CustomRowView, null);
var imgUrl = string.Format(@"http://myserver.com/?action={0}&url={1}", "get.thumbnail", item.Image.Url);
//Here is the image loading row
view.FindViewById<ImageView>(Resource.Id.imageView1).SetUrlDrawable(imgUrl);
view.FindViewById<TextView>(Resource.Id.txtTitle).Text = item.Title;
view.FindViewById<TextView>(Resource.Id.txtYear).Text = item.Information.Year;
view.FindViewById<TextView>(Resource.Id.txtGenre).Text = item.Information.Genre;
view.FindViewById<TextView>(Resource.Id.txtGrade).Text = item.Rating.Grade;
view.FindViewById<TextView>(Resource.Id.txtVotes).Text = string.Format("( {0} )", item.Rating.Votes);
return view;
}
加载页面函数
public void LoadPage()
{
OnUpdateAnimeListStart(); //Event to display loading message
try
{
this._items.FillListFromUrl(string.Format("http://myserver.com/page/{0}/", this._page));
}
catch(Exception ex)
{
_context.RunOnUiThread(() =>
{
new AlertDialog.Builder(_context)
.SetPositiveButton("Ok", (sender, args) =>
{
Intent blankIntent = new Intent();
blankIntent.SetFlags(ActivityFlags.ClearTop);
int intPID = Android.OS.Process.MyPid();
Android.OS.Process.KillProcess(intPID);
})
.SetMessage(ex.Message)
.SetTitle("Error!")
.Show();
});
}
this._page++;
_context.RunOnUiThread(() =>
{
_context.FindViewById<ListView>(Resource.Id.listView).InvalidateViews();
});
OnUpdateAnimeListEnd(); //Event to hide loading message
}
这是我谈到的替代“队列”
public class ImageDownloader
{
private List<ImageView> _queueImageViews;
private List<string> _queueImageUrls;
private Activity _context;
public ImageDownloader(Activity context)
{
this._context = context;
this._queueImageViews = new List<ImageView>();
this._queueImageUrls = new List<string>();
}
public void DownloadImage(ImageView imgView, string url)
{
this._queueImageViews.Add(imgView);
this._queueImageUrls.Add(url);
if (this._queueImageViews.Count == 1)
this._startJob();
}
private void _startJob()
{
WebClient web = new WebClient();
web.DownloadDataCompleted += new DownloadDataCompletedEventHandler(web_DownloadDataCompleted);
web.DownloadDataAsync(new Uri(this._queueImageUrls[0]));
}
private void _removeFromeQueue(int index = 0)
{
this._queueImageUrls.Remove(this._queueImageUrls[index]);
this._queueImageViews.Remove(this._queueImageViews[index]);
}
void web_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
{
ImageView v = this._queueImageViews[0];
this._context.RunOnUiThread(() =>
{
Bitmap bm = BitmapFactory.DecodeByteArray(e.Result, 0, e.Result.Length);
v.SetImageBitmap(bm);
});
this._removeFromeQueue();
if (this._queueImageViews.Count > 0)
this._startJob();
}
}
提前谢谢你。
【问题讨论】:
-
这不是您问题的答案,但您可以考虑使用此加载器,因为它来自官方 Android 开发者博客。 developer.android.com/training/displaying-bitmaps/…
-
我会看一下,可能会尝试将其移植到 monodroid,但我敢打赌,其他 monodroid 开发人员已经找到了解决此类问题的方法,而我没有不想重新发明轮子。但如果没有其他选择 - 那么就没有其他选择:)
-
我不想绕开你,只是好奇你为什么认为问题出在图像缓存上?是不是下载图片的代码没有关闭网络连接?
-
@Y2i,首先 - 谢谢!在 UrlImageViewHelper 端口中,创建者实际上忘记了关闭连接。我解决了这个问题,但不幸的是这仍然没有解决我的问题:(我认为问题出在这个方法缓存中,因为缓存部分中存在未定义的异常。但这可能不是问题的根源......
-
试用 Google 的 volley 库。 developers.google.com/live/shows/474338138 。它可以有效地加载图像并填充 listView
标签: c# android listview xamarin.android xamarin