【问题标题】:My listview keeps refreshing the images with the LogoLoader Asynctask我的列表视图使用 LogoLoader Asynctask 不断刷新图像
【发布时间】:2013-10-08 08:39:43
【问题描述】:

我的列表视图有一个自定义适配器,在列表视图中,它为每个图像设置一个异步任务,以在后台从 web 服务加载图像,然后显示它。但是图像不断刷新,有时会在一段时间后加载错误的图像。(第一次加载它显示正确的图像)LogoLoader 是异步任务。

适配器类:

public class SearchResultAdapter extends ArrayAdapter<SearchResultRowItem> {

Context context;
private MainActivity main;

public SearchResultAdapter(Context context, int resourceId, List<SearchResultRowItem> items,MainActivity main) {
    super(context, resourceId, items);
    this.context = context;
    this.main = main;
}

/*private view holder class*/
private class ViewHolder {
    ImageView imageView;
    TextView txtTitle;
    TextView txtDesc;
    TextView txtAdres;
    TextView txtAfstand;
}

public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder = null;
    SearchResultRowItem rowItem = getItem(position);

    LayoutInflater mInflater = (LayoutInflater) context
            .getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
    if (convertView == null) {
        convertView = mInflater.inflate(R.layout.listitem, null);
        holder = new ViewHolder();
        holder.txtDesc = (TextView) convertView.findViewById(R.id.desc);
        holder.txtTitle = (TextView) convertView.findViewById(R.id.title);
        holder.txtAdres = (TextView) convertView.findViewById(R.id.adres);
        holder.txtAfstand = (TextView) convertView.findViewById(R.id.afstand);
        holder.imageView = (ImageView) convertView.findViewById(R.id.logo);
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }


    holder.txtDesc.setText(Html.fromHtml(rowItem.getDesc()));
    holder.txtTitle.setText(rowItem.getTitle());
    holder.txtAdres.setText(rowItem.getAdres());
    holder.txtAfstand.setText(rowItem.getAfstand());

    if (holder.imageView != null && rowItem.hasLogo()) {
        holder.imageView.setImageResource(R.drawable.loader);
        LogoLoader logoLoader = new LogoLoader(holder.imageView, rowItem.getOrganisatieId(), 100, 100, main);
        logoLoader.execute();
    }

    convertView.setBackgroundColor(position % 2 == 0 ? Color.WHITE : Color.parseColor("#F8F8F8"));
    return convertView;
}

}

LogoLoader 类:

public class LogoLoader extends AsyncTask<Void, Void, String> {

private ImageView imageView;
private UUID OrganisationGuid;
private int maxWidth;
private int maxHeight;

private MainActivity main;

public LogoLoader(ImageView imageView, UUID OrganisationGuid, int maxHeight, int maxWidth,MainActivity main) {
    this.imageView = imageView;
    this.OrganisationGuid = OrganisationGuid;
    this.maxHeight = maxHeight;
    this.maxWidth = maxWidth;
    this.main = main;
}

@Override
protected String doInBackground(Void... params) {
    WebserviceAdapter task = new WebserviceAdapter(
            "api/Logo/GetLogos?ids="+OrganisationGuid.toString()+
            "&maxWidth="+Integer.toString(maxWidth)+
            "&maxHeight="+Integer.toString(maxHeight));
    return task.result;
}

@Override
protected void onPostExecute(String result){
    try {
        JSONObject json = new JSONObject(result);

        JSONArray jsonArray = json.getJSONArray("Results");
        JSONObject imageObject = jsonArray.getJSONObject(0);

        byte[] imageData = Base64.decode( imageObject.getString("Data").getBytes(), Base64.DEFAULT);
        Drawable logoDrawable = null;
        if (imageData != null) {
            Bitmap logoBitmap = BitmapFactory.decodeByteArray(imageData, 0,
                    imageData.length);
            logoDrawable = new BitmapDrawable(main.getResources(), logoBitmap);
        }
        imageView.setImageDrawable(logoDrawable);
    } catch (JSONException e) {
        imageView.setImageDrawable(null);
    }

}

}

【问题讨论】:

    标签: java android android-listview android-asynctask listadapter


    【解决方案1】:

    重复加载是由于listview的getView方法被定期调用多次,加载错误的图像是由于resuing view的特性。 ListView 尝试重用项目视图以节省内存并提高效率。第一个问题的解决方案是只加载一次图像并将其保存在某处(如果图像是缩略图,则在内存中,如果图像更大,则在 SDCard 上)。第二个问题的解决方案是使用

    holder.imageView.setImageBitmap(null);
    

    if (holder.imageView != null &amp;&amp; rowItem.hasLogo()) { 之前,这样无论何时渲染视图,它都不会加载以前的图像。 我希望你明白我的意思。您还可以使用通用图像加载器库来加载图像。我用过它,它就像一个魅力。

    【讨论】:

    • 谢谢你帮了我大忙,我稍后再做缓存!
    【解决方案2】:

    我可以推荐一种不同的加载图像的方法,它就像一个魅力:Android Query。

    您可以从这里下载该 jar 文件:http://code.google.com/p/android-query/downloads/list

    AQuery androidAQuery=new AQuery(this);
    

    举个例子:

    androidAQuery.id(YOUR IMAGEVIEW).image(YOUR IMAGE TO LOAD, true, true, getDeviceWidth(), ANY DEFAULT IMAGE YOU WANT TO SHOW);
    

    它非常快速和准确,使用它您可以在加载时找到更多功能,例如动画;如果需要,获取位图;等等

    【讨论】:

    • 感谢您抽出宝贵时间来回答,但我想知道我做错了什么,以便从中吸取教训。
    • 您的呼叫在后台运行,因此它将是一项单独的任务,而您膨胀数据是另一项任务,因此两者都不会并行运行。我已经为此提供了一个完美的解决方案,您可以从您的应用程序中保存一个异步任务,并且 android 查询将像魅力一样工作。试试看吧。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-14
    • 1970-01-01
    • 2013-01-15
    • 1970-01-01
    相关资源
    最近更新 更多