在android中滚动listView时重新加载图像

Posted

技术标签:

【中文标题】在android中滚动listView时重新加载图像【英文标题】:Image reloaded when scroll listView in android 【发布时间】:2015-10-23 03:42:37 【问题描述】:

我正在尝试编写一个新闻列表应用程序。我已经解析了来自服务器的 JSON 数据并创建了 CustomListAdapter。我的 listView 中有三个 textView 和 imageView。它工作得很好,加载了图像,我将它设置为 imageView。当从服务器重新加载滚动列表视图图像时。这是我的片段:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) 
    View rootView = inflater.inflate(R.layout.news_fragment, container, false);
    this.drawerPosition = getArguments().getInt(ARG_PLANET_NUMBER);
    lv = (ListView) rootView.findViewById(R.id.listView);
    View v = inflater.inflate(R.layout.list_footer, null);
    lv.addFooterView(v);
    isLoading = true;
    Http.getLists(aContext, this.drawerPosition, pageNumber, resultHandler);
    lv.setOnScrollListener(new AbsListView.OnScrollListener() 
        @Override
        public void onScrollStateChanged(AbsListView absListView, int i) 
        

        @Override
        public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount) 
            int l = visibleItemCount + firstVisibleItem;
            if (l >= totalItemCount && !isLoading) 
                // It is time to add new data. We call the listener
                isLoading = true;
                Http.getLists(aContext, drawerPosition, pageNumber, appendHandler);
            
        
    );
    return rootView;


public void setListview() 
    listAdapter = new ListViewCustomAdapter(aContext, arrayList);
    lv.setAdapter(listAdapter);


AsyncHttpResponseHandler resultHandler = new AsyncHttpResponseHandler() 
    @Override
    public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) 
        if (statusCode != 200)
            return;
        try 
            JSONObject json = new JSONObject(new String(responseBody));
            Log.d("JSON Result: ", json.toString());
            String result = json.getString("status");
            if (result.equalsIgnoreCase("complete")) 
                String pagenum = json.getString("pagenum");
                JSONArray items = json.getJSONArray("items");
                ArrayList<NewsList> s = new ArrayList<NewsList>();
                for (int i = 0; i < items.length(); i++) 
                    s.add(new NewsList(
                            Integer.parseInt(items.getJSONObject(i).getString("ID")),
                            items.getJSONObject(i).getString("post_date"),
                            items.getJSONObject(i).getString("category"),
                            items.getJSONObject(i).getString("post_title"),
                            items.getJSONObject(i).getString("image")
                    ));
                
                arrayList = s;
                isLoading = false;
                pageNumber = Integer.valueOf(pagenum) + 1;
                setListview();
            
         catch (JSONException e) 
            e.printStackTrace();
        
    

    @Override
    public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) 
        String answ = error.getLocalizedMessage();
        Log.d("API", answ);
    
;

这是我的自定义 ListView 适配器:

@Override
public View getView(int position, View convertView, ViewGroup parent) 
    // TODO Auto-generated method stub
    ViewHolder holder;

    if (convertView == null) 
        convertView = inflater.inflate(R.layout.row, null);

        holder = new ViewHolder();
        holder.nTitle = (TextView) convertView.findViewById(R.id.listTitle);
        holder.nDate = (TextView) convertView.findViewById(R.id.listDate);
        holder.nCategory = (TextView) convertView.findViewById(R.id.listCategory);
        holder.nImage = (ImageView) convertView.findViewById(R.id.listImage);
        convertView.setTag(holder);
     else
        holder = (ViewHolder) convertView.getTag();


    if (newsList.get(position) != null) 
        holder.imageUrl = newsList.get(position).image;
        holder.nTitle.setText(newsList.get(position).title);
        holder.nCategory.setText(newsList.get(position).category);
        holder.nDate.setText(Base.getInstance(context).getDateString(newsList.get(position).date));
        if (holder.imageUrl != null && !holder.imageUrl.equals("null")) 
            String thumbUrl = holder.imageUrl.substring(0, holder.imageUrl.lastIndexOf('.')) + "-260x145" + holder.imageUrl.substring(holder.imageUrl.lastIndexOf('.'), holder.imageUrl.length());
            imageView = holder.nImage;
            setImage(thumbUrl);
        
    

    return convertView;


private static class ViewHolder 
    TextView nTitle;
    TextView nDate;
    TextView nCategory;
    ImageView nImage;
    String imageUrl;


public void setImage(String imageUrl) 
    AsyncHttpClient client = new AsyncHttpClient();
    client.get(imageUrl, null, fileHandler);


FileAsyncHttpResponseHandler fileHandler = new FileAsyncHttpResponseHandler(context) 
    @Override
    public void onFailure(int statusCode, Header[] headers, Throwable throwable,
                          File response) 
    

    @Override
    public void onSuccess(int statusCode, Header[] headers, File response) 
        imageView.setImageBitmap(BitmapFactory.decodeFile(response.getPath()));
    
;

【问题讨论】:

问题是什么? 您没有有效地使用 View Holder 模式。每次 Listview 滚动时,它都会创建新的 ViewHolder 对象,其中您的图像数据将不存在。这就是为什么图像将在每个列表视图滚动上重新生成。请看javacodegeeks.com/2013/09/…教程。 Dhaval Patel 我阅读了本教程,并更新了代码,但没有帮助。每次滚动时都会重新加载图像。 @iProgrammer 请更新您的代码,以便我们查看您的新代码。 我更新了新代码。请检查... 【参考方案1】:

试试下面的代码,它可能会帮助你解决你的问题。

public class ListViewCustomAdapter extends..

   //Map to cache Image Bitmap. Key= imageUrl,value =Image Bitmap
   private Map<String, Bitmap> mBitmapCache = new HashMap<String, Bitmap>();    

   @Override
   public View getView(int position, View convertView, ViewGroup parent) 
      ViewHolder holder;

      if (convertView == null) 
          convertView = inflater.inflate(R.layout.row, null);
          holder = new ViewHolder();
          holder.nTitle = (TextView) convertView.findViewById(R.id.listTitle);
          holder.nDate = (TextView) convertView.findViewById(R.id.listDate);
          holder.nCategory = (TextView) convertView.findViewById(R.id.listCategory);
          holder.nImage = (ImageView) convertView.findViewById(R.id.listImage);
          convertView.setTag(holder);
       else 
          holder = (ViewHolder) convertView.getTag();
       

      if (newsList.get(position) != null) 
          holder.imageUrl = newsList.get(position).image;
          holder.nTitle.setText(newsList.get(position).title);
          holder.nCategory.setText(newsList.get(position).category);
          holder.nDate.setText(Base.getInstance(context).getDateString(newsList.get(position).date));
          if (holder.imageUrl != null && !holder.imageUrl.equals("null")) 
               String thumbUrl = holder.imageUrl.substring(0, holder.imageUrl.lastIndexOf('.')) + "-260x145" + holder.imageUrl.substring(holder.imageUrl.lastIndexOf('.'), holder.imageUrl.length());
               holder.setImage(thumbUrl);
          
      
      return convertView;
   

   private static class ViewHolder 
        TextView nTitle;
        TextView nDate;
        TextView nCategory;
        ImageView nImage;
        String imageUrl;

        public void setImage(String imageUrl) 
           this.imageUrl = imageUrl;
           Bitmap imageBitmap = mBitmapCache.get(imageUrl);
           if(imageBitmap!=null)
               nImage.setImageBitmap(imageBitmap);
            else 
               AsyncHttpClient client = new AsyncHttpClient();
               client.get(imageUrl, null, fileHandler);
           
        

        FileAsyncHttpResponseHandler fileHandler = new FileAsyncHttpResponseHandler(context) 
             @Override
             public void onFailure(int statusCode, Header[] headers, Throwable throwable,
                      File response) 
             

             @Override
             public void onSuccess(int statusCode, Header[] headers, File response) 
                   Bitmap imageBitmap = BitmapFactory.decodeFile(response.getPath());
                   imageView.setImageBitmap(imageBitmap);
                   mBitmapCache.put(imageUrl, imageBitmap);         
             
        ;
    

【讨论】:

非常感谢。它真的帮助了我。你写了不正确的 imageBitmap.put(imageUrl, imageBitmap)。必须是 mBitmapCache.put(imageUrl, imageBitmap);【参考方案2】:

你的代码在

public void setImage() 
    if (imageUrl != null && !imageUrl.equals("null") && !imageUrl.equals("")) 
        AsyncHttpClient client = new AsyncHttpClient();
        client.get(imageUrl, null, fileHandler);
    

看起来很可疑:任何有效的 URL 都将强制重新加载,因为它匹配中的所有三个条件

    imageUrl != null && !imageUrl.equals("null") && !imageUrl.equals("")

示例: http://www.google.com/logo.png 不为空,不等于字符串“null”或字符串“”,因此 if 将始终为 true 并创建 AsyncLoader。 顺便说一句,仅当您在代码中的其他地方明确使用它时,检查“null”才有意义。很可能您只想检查空值,而不是“空”字符串。

【讨论】:

以上是关于在android中滚动listView时重新加载图像的主要内容,如果未能解决你的问题,请参考以下文章

Android 在加载联系人照片时平滑 ListView 滚动

在没有重新加载活动/布局之前启动活动

listitem中的Android listview imageview在滚动时隐藏

listitem中的Android listview imageview在滚动时隐藏

ListView 在滚动时不会更改元素

Android中的Listview延迟加载平滑[重复]