Android Volley - 当加载图片时在listview适配器中显示进度条

3

我尝试使用Volley在listview项中从网络获取图片。当下载图片时,进度条会显示,在完成后应该隐藏。

这是我的适配器:

   public class NewsAdapter  extends CursorAdapter{
public NewsAdapter(Context context, Cursor c) {
    super(context, c, true);
}

@Override
public Cursor getItem(int position) {
    return (Cursor) super.getItem(position);
}

@Override
public void bindView(View view, final Context context, Cursor cursor) {
    final NetworkImageView imgNewsItem = (NetworkImageView) view.findViewById(R.id.imgNewsItem); 
    final ProgressBar progressNewsList = (ProgressBar) view.findViewById(R.id.progressNewsList);

    progressNewsList.setVisibility(View.VISIBLE);
    imgNewsItem.setVisibility(View.GONE);
    Ln.d("get news image: %s", cursor.getString(cursor.getColumnIndex(News.IMAGE_COLUMN)));
    ImageCacheManager.getInstance().getImageLoader().get(cursor.getString(cursor.getColumnIndex(News.IMAGE_COLUMN)), new ImageListener() {

        @Override
        public void onErrorResponse(VolleyError error) {
            Ln.e(error);
            progressNewsList.setVisibility(View.GONE);
            imgNewsItem.setVisibility(View.VISIBLE);
            imgNewsItem.setImageResource(R.drawable.news_default_image);
        }

        @Override
        public void onResponse(ImageContainer response, boolean isImmediate) {
            progressNewsList.setVisibility(View.GONE);
            imgNewsItem.setVisibility(View.VISIBLE);
            imgNewsItem.setImageBitmap(response.getBitmap());
        }
    });
}

@Override
public View newView(Context arg0, Cursor arg1, ViewGroup parent) {
    LayoutInflater inflater = LayoutInflater.from(parent.getContext());
    View retView = inflater.inflate(R.layout.row_view, parent, false);
    return retView;
}

我已经调试过了,发现Volley下载和缓存图片位图是正常的,但是ImageView不显示。

我的项目布局如下:

 <LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="5dp" >

    <com.android.volley.toolbox.NetworkImageView
        android:id="@+id/imgNewsItem"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:scaleType="fitXY"
        android:src="@drawable/news_default_image"
      android:visibility="gone" />

    <ProgressBar
        android:id="@+id/progressNewsList"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center" 
        >
    </ProgressBar>
</LinearLayout>

这个示例中的ImageCacheManager来自于: https://github.com/rdrobinson3/VolleyImageCacheExample。请问我哪里做错了?谢谢预先帮助。

更新: 另外,下载时进度条没有显示。

说实话,我不明白你是怎么按照示例操作的。我认为你不应该调用loaderget方法。你试过这样吗:imgNewsItem.setImageUrl(<url>, ImageCacheManager.getInstance().getImageLoader()); - Amulya Khare
但是我需要监听器隐藏进度条。 - ductran
你为什么要隐藏 ProgressBar,尽管你必须要 dismiss(); 它。 - GrIsHu
@GrIsHu 因为我不想显示进度对话框,我只想在下载图片时有一个带圆形的进度条。 - ductran
3个回答

1
你需要更改ImageListener.onResponse方法为以下内容:
@Override
public void onResponse(ImageContainer response, boolean isImmediate) {
    Bitmap bitmap = response.getBitmap();
    if(bitmap != null){
       progressNewsList.setVisibility(View.GONE);
       imgNewsItem.setVisibility(View.VISIBLE);
       imgNewsItem.setImageBitmap(bitmap);
   }
}

以下是 ImageListener 的 Java 文档:
接口用于处理图像请求的响应处理程序。调用流程如下: 1. 一旦附加到请求上,将调用onResponse(response, true)以反映任何已经可用的缓存数据。如果数据可用,则response.getBitmap()将为非null。 2. 网络响应返回后,只会发生以下情况之一: - 如果加载了图像,则将调用onResponse(response, false)。 - 如果加载图片时出现错误,则将调用 onErrorResponse。

1
LinearLayout 改为 FrameLayout,并更改顺序,使进度条在 NetworkImageView 之前,像这样。
<FrameLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_margin="5dp" >

<ProgressBar
        android:id="@+id/progressNewsList"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center" 
        >
    </ProgressBar>

    <com.android.volley.toolbox.NetworkImageView
        android:id="@+id/imgNewsItem"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:scaleType="fitXY"
        android:src="@drawable/news_default_image"
      android:visibility="gone" />


</FrameLayout>

Java代码

我正在使用在RecycleView适配器中

@Override
    public void onBindViewHolder(final ViewHolder holder, int position) {
      ImageLoader _ImageLoader = MySingleton.getInstance(_Context).getmImageLoader();


        String url = "...."; // your image url
  holder.ProgressBar.setVisibility(View.VISIBLE);
            _ImageLoader.get(url, new ImageLoader.ImageListener() {
                @Override
                public void onResponse(ImageLoader.ImageContainer response, boolean isImmediate) {
                    if (response.getBitmap() != null) {
                        holder.ProgressBar.setVisibility(View.GONE);
                        holder.imageView.setImageBitmap(response.getBitmap());
                    }

                }
                @Override
                public void onErrorResponse(VolleyError error) {

                }
            });
}

我的单例类

public class MySingleton {

    private static MySingleton mInstance;
    private Context mContext;
    private RequestQueue mResquestQueue;
    private ImageLoader mImageLoader;

    private MySingleton(Context mCtx){
        this.mContext = mCtx;
        mResquestQueue = Volley.newRequestQueue(MyApplication.getAppContext());
        mImageLoader = new ImageLoader(mResquestQueue , new ImageLoader.ImageCache(){
            private final LruCache<String , Bitmap> cache = new LruCache<>(20);

            @Override
            public Bitmap getBitmap(String url) {
                return cache.get(url);
            }

            @Override
            public void putBitmap(String url, Bitmap bitmap) {
                   cache.put(url , bitmap);

            }
        });

    }

    public static synchronized MySingleton getInstance(Context context){
        if(mInstance == null){
            mInstance = new MySingleton(context);
        }
        return mInstance;

    }

    public RequestQueue getResquestQueue(){
        if(mResquestQueue == null){
            mResquestQueue= Volley.newRequestQueue(mContext.getApplicationContext());
        }
        return mResquestQueue;
    }

    public <T> void addToRequestQueue(Request<T> request){
          mResquestQueue.add(request);
    }

    public ImageLoader getmImageLoader(){
        return mImageLoader;
    }

    public void CancelAllRequestes(){
        if(mResquestQueue != null){
            mResquestQueue.cancelAll(this);
        }
    }

}

1
如果您使用方法来加载图像,并且ProgressBar在不同的方法中已经初始化,则在onResponse(...)上隐藏ProgressBar可能无法正常工作,因此您需要将ProgressBar作为参数传递。
private void loadImage(String imageUrl, final ImageView imageView, final ProgressBar progressBar) {
    //progressBar.setVisibility(View.VISIBLE);
    if (imageUrl != null) {
        mImageLoader.get(imageUrl, new ImageLoader.ImageListener() {

            @Override
            public void onResponse(ImageLoader.ImageContainer response, boolean isImmediate) {
                if (response.getBitmap() != null) {
                    progressBar.setVisibility(View.GONE);
                    imageView.setImageBitmap(response.getBitmap());
                }
            }

            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e("onErrorResponse ", error.toString());
                progressBar.setVisibility(View.GONE);
            }
        });
    }
}

你的回答有一些问题。首先,如果imageUrl为null,imageUrl.equals(null)会抛出NullpointerException,你应该使用imageUrl != null。其次,将ProgressBar作为参数传递没有任何意义,这与我的bindView方法相同。 - ductran
我同意你的第一个观点,并且我已经编辑了我的答案。对于你的第二个观点,你只是在bindview方法中初始化和处理ProgressBar,所以没有问题,但是如果你在不同的方法中使用并处理在bindview中初始化的ProgressBar,它将无法正常工作。 - Sushil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接