Volley学习(四)NetworkImageView+LruCache(源码简读)图片请求小例子

代码下载 点击链接,免积分下载。。。

今天来写一个关于图片请求的小例子,我们用NetworkImageView这个类来实现,这个类可以直接用在xml控件中,当作imageview,而且内部原理也是使用的ImageLoader,所以综合性还是不错的
效果图如下:
Volley学习(四)NetworkImageView+LruCache(源码简读)图片请求小例子_第1张图片

本例就没有再去进行封装代码了,封装代码在前几篇中有写到,下面2张图是
http://www.imooc.com/api/teacher?type=4&num=30返回的json格式的数据,本例也就从中获取picSmall、name即可

Volley学习(四)NetworkImageView+LruCache(源码简读)图片请求小例子_第2张图片

下面就是onResponse返回的一串字符串(只不过这个字符串的格式是Json类型)

    StringRequest request = new StringRequest(Method.GET, url,
                new Listener() {
                    @Override
                    public void onResponse(String sb) {
                        Log.e("Safly", "onResponse-->>" + sb);
                        parseJsonFromServer(sb);
                        setAdapter();
                    }
            }, new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError arg0) {
                    }
                });

然后就开始解析,用JsonObject(当然也可以用JsonObject的另外写法比如jsonObject.optInt的写法,还可以用JsonReader等等)

    private void parseJsonFromServer(String sb) {
        datas = new ArrayList();
        JSONObject jsonObject;
        try {
            jsonObject = new JSONObject(sb.toString());
            JSONArray jsonArray = jsonObject
                    .getJSONArray("data");
            for (int i = 0; i < jsonArray.length(); i++) {
                JSONObject jsonData = jsonArray
                        .getJSONObject(i);
                DataBean newsBean = new DataBean();
                newsBean.setImageUrl(jsonData
                        .getString("picSmall"));
                newsBean.setTitle(jsonData.getString("name"));
                // 添加对象,组建集合
                datas.add(newsBean);
            }
            Log.i("Safly", "datas.size-->>"+datas.size());
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

最后就看adapter中的内容即可
我们在稍微看下NetworkImageView源码类
Volley学习(四)NetworkImageView+LruCache(源码简读)图片请求小例子_第3张图片

它里面有2个方法是进行设置控件的默认图片,以及下载失败的提示图片,结果这2个方法在Volley中都没有内部调用,所以说我们可以在adapter中,进行预设置,我们之前看源码得知,下载完毕图片后,还会进行更新操作,下载失败后,就会volley内部去进行操作

    /**
       * 接下来就是跟imageloader里面的请求代码思路一样了
       */
        ImageContainer newContainer = mImageLoader.get(mUrl,
                new ImageListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        if (mErrorImageId != 0) {
                            setImageResource(mErrorImageId);
                        }
                    }

然后我们就可以利用如下的源码进行设置了一些参数了,下边是volley的代码

   public void setImageUrl(String url, ImageLoader imageLoader) {
        mUrl = url;
        mImageLoader = imageLoader;
        // The URL has potentially changed. See if we need to load it.
        loadImageIfNecessary(false);
    }

对应我们代码中的部分

 viewHolder.imageview_item.setImageUrl(url, VolleyTool.getInstance(context).getImageLoader()); 
  //私有构造方法  
    private VolleyTool(Context context) {  
        //创建请求队列  
        queue = Volley.newRequestQueue(context);  
        //创建图片加载器  
        imageLoader = new ImageLoader(queue, new LruImageCache());  
    }  
    //公共、静态的方法  
    public static VolleyTool getInstance(Context context) {  
        if (instance == null) {  
            instance = new VolleyTool(context);  
        }  
        return instance;  
    }  

看看构造器中进行了哪些操作?初始化queue、ImageLoader
我们在看看对应volley中的ImageLoader的构造器部分如下:

    public interface ImageCache {
        public Bitmap getBitmap(String url);
        public void putBitmap(String url, Bitmap bitmap);
    }

    /**
     * Constructs a new ImageLoader.
     * @param queue The RequestQueue to use for making image requests.
     * @param imageCache The cache to use as an L1 cache.
     */
    public ImageLoader(RequestQueue queue, ImageCache imageCache) {
        mRequestQueue = queue;
        mCache = imageCache;
    }

很明显源码中ImageCache,只有getBitmap、putBitmap方法,而我们呢?用到了LruCache强缓存处理,以完善内存缓存的控制管理

那我们就来看看这个LruChche的源码把如下:
首先看看构造器部分:

  /**
     * @param maxSize for caches that do not override {@link #sizeOf}, this is
     *     the maximum number of entries in the cache. For all other caches,
     *     this is the maximum sum of the sizes of the entries in this cache.
     */
    public LruCache(int maxSize) {
        if (maxSize <= 0) {
            throw new IllegalArgumentException("maxSize <= 0");
        }
        this.maxSize = maxSize;
        this.map = new LinkedHashMap(0, 0.75f, true);
    }

如果maxSize<=0 就会跑异常,那么这个参数是什么意思呢?
我们看看百度的翻译:这是高速缓存中的条目的最大数目。对于所有其他高速缓存,这是该缓存中的项的大小的最大和。
意思就是此缓存能缓存的最大值是多少

缓存肯定需要放东西把,我们看看put做了什么相关处理的操作?

    public final V put(K key, V value) {
        if (key == null || value == null) {
            throw new NullPointerException("key == null || value == null");
        }

        V previous;
        synchronized (this) {
            putCount++;
            size += safeSizeOf(key, value);
            previous = map.put(key, value);
            if (previous != null) {
                size -= safeSizeOf(key, previous);
            }
        }

        if (previous != null) {
            entryRemoved(false, key, previous, value);
        }

        trimToSize(maxSize);
        return previous;
    }

大概意思就是:放进来一个就putCount++就累加进来数量,参数一看就知道啥意思了,那么safeSizeOf这个是啥意思呢?我们去看看


    private int safeSizeOf(K key, V value) {
        int result = sizeOf(key, value);
        if (result < 0) {
            throw new IllegalStateException("Negative size: " + key + "=" + value);
        }
        return result;
    }
    protected int sizeOf(K key, V value) {
        return 1;
    }

针对到本例子就是请求的一个图片的内存大小,请求一个就累加size += safeSizeOf(key, value);我们该问了,它对存在的还会累加么?我们在回到put方法中,

if (previous != null) {
                size -= safeSizeOf(key, previous);
            }

这个意思是如果之前有缓存的话,就不再添加了,就在剪掉即可
最后看下put方法中的代码
trimToSize(maxSize);
他的意思就是删除最大的条目,直到剩余的条目总数或低于所请求的大小。百度翻译的意思就是,容量超过就会删除访问少的条目

get方法也就相对简单了,就是取出来就可。

所以我们的代码在看的话,就不是那么复杂了:


    /** 
     * 使用LRU回收算法的缓存类 
     */  
    class LruImageCache implements ImageCache {  

        // 缓存容器  
        private LruCache cache;  

        public LruImageCache() {  
            // 计算缓存的最值  
            int maxSize = (int) (Runtime.getRuntime().maxMemory() / 8);  
            //创建缓存对象实例  
            cache = new LruCache(maxSize) {  
                @Override  
                protected int sizeOf(String key, Bitmap value) {  
                    // 返回bitmap占用的内存大小  
                    return value.getRowBytes() * value.getHeight();  
                }  
            };  
        }  

        // 从缓存中取图片对象  
        @Override  
        public Bitmap getBitmap(String url) {  
            return cache.get(url);  
        }  

        // 将图片对象保存到缓存容器中  
        @Override  
        public void putBitmap(String url, Bitmap bitmap) {  
            cache.put(url, bitmap);  
        }  

    }  

另外注意一点就是在item布局中

  <com.android.volley.toolbox.NetworkImageView
         android:scaleType="fitXY"  
        android:background="@drawable/ic_launcher"
        android:id="@+id/imageview_item"  
        android:layout_width="60dp"  
        android:layout_height="60dp"/> 

需要android:scaleType=”fitXY”

我这个demo没有出现图片错乱的现象,有的朋友说会有错乱的现象,我做了一个实验,初始化有网络,然后就关掉网络,进行滑动依然是没有问题的如下:
Volley学习(四)NetworkImageView+LruCache(源码简读)图片请求小例子_第4张图片

另外下载的图片缓存到哪里去了呢?如下
Volley学习(四)NetworkImageView+LruCache(源码简读)图片请求小例子_第5张图片

以下就是代码区别############################


"http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.saflyimage.MainActivity" >

    "@+id/mListView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" />




"1.0" encoding="utf-8"?>
"http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:background="#FFFFF0"
    android:layout_height="wrap_content" >

     "fitXY"  
        android:background="@drawable/ic_launcher"
        android:id="@+id/imageview_item"  
        android:layout_width="60dp"  
        android:layout_height="60dp"/>  


    "tv"
        android:layout_marginRight="20dp"
        android:layout_centerVertical="true"
        android:layout_alignParentRight="true"
        android:id="@+id/textview_item"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />




SaflyApplication

package com.example.saflyimage;

import android.app.Application;

import com.android.volley.RequestQueue;
import com.android.volley.toolbox.Volley;


public class SaflyApplication extends Application {
    public static RequestQueue requestQueue;
    @Override
    public void onCreate() {
        super.onCreate();
        requestQueue = Volley.newRequestQueue(getApplicationContext());
    }
    public static RequestQueue getRequestQueue() {
        return requestQueue;
    }
}


DataBean

package com.example.saflyimage;

public class DataBean {
    private String imageUrl;

    private String title;

    public DataBean(String imageUrl, String title) {
        super();
        this.imageUrl = imageUrl;
        this.title = title;
    }

    public DataBean() {
        super();
        // TODO Auto-generated constructor stub
    }

    public String getImageUrl() {
        return imageUrl;
    }

    public void setImageUrl(String imageUrl) {
        this.imageUrl = imageUrl;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }



}


MainActivity

package com.example.saflyimage;

import java.util.ArrayList;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.widget.ListView;

import com.android.volley.Request.Method;
import com.android.volley.Response;
import com.android.volley.Response.Listener;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;

public class MainActivity extends Activity {
    private List datas;

    private ListView mListView;
    private SaflyAdapter saflyAdapter; 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mListView = (ListView) findViewById(R.id.mListView);
        String url = "http://www.imooc.com/api/teacher?type=4&num=30";

        StringRequest request = new StringRequest(Method.GET, url,
                new Listener() {

                    @Override
                    public void onResponse(String sb) {
                        Log.e("Safly", "onResponse-->>" + sb);
                        parseJsonFromServer(sb);
                        setAdapter();
                    }

                }, new Response.ErrorListener() {

                    @Override
                    public void onErrorResponse(VolleyError arg0) {

                    }
                });
        // 设置标签
        request.setTag("abcGet");
        SaflyApplication.getRequestQueue().add(request);
        SaflyApplication.getRequestQueue().start();
    }

    /**
     * 设置适配器
     */
    private void setAdapter() {
        saflyAdapter = new SaflyAdapter(MainActivity.this,datas);

        mListView.setAdapter(saflyAdapter);

    }
    /**
     * 解析json数据
     * @param sb
     */
    private void parseJsonFromServer(String sb) {
        datas = new ArrayList();
        JSONObject jsonObject;
        try {
            jsonObject = new JSONObject(sb.toString());
            JSONArray jsonArray = jsonObject
                    .getJSONArray("data");
            for (int i = 0; i < jsonArray.length(); i++) {
                JSONObject jsonData = jsonArray
                        .getJSONObject(i);
                DataBean newsBean = new DataBean();
                newsBean.setImageUrl(jsonData
                        .getString("picSmall"));
                newsBean.setTitle(jsonData.getString("name"));
                // 添加对象,组建集合
                datas.add(newsBean);
            }
            Log.i("Safly", "datas.size-->>"+datas.size());
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
}


SaflyAdapter

package com.example.saflyimage;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import com.android.volley.toolbox.NetworkImageView;

public class SaflyAdapter extends BaseAdapter {

    private ArrayList dataBeans;
    private Context context;
    private LayoutInflater inflater;

    public SaflyAdapter(Context context, List datas) {
        super();
        this.dataBeans = (ArrayList) datas;
        this.context = context;
        this.inflater = LayoutInflater.from(context);
    }

    @Override
    public int getCount() {
        return dataBeans.size();
    }

    @Override
    public Object getItem(int position) {
        // TODO Auto-generated method stub
        return dataBeans.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final ViewHolder viewHolder;
        if (convertView == null) {
            convertView = inflater.inflate(R.layout.listview_item, parent,
                    false);
            viewHolder = new ViewHolder(convertView);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }

        DataBean dataBean = dataBeans.get(position);
        viewHolder.textview_item.setText(dataBean.getTitle());

        // 设置未加载默认图片
        viewHolder.imageview_item.setDefaultImageResId(R.drawable.ic_launcher);
        // 设置加载异常的图片
        viewHolder.imageview_item.setErrorImageResId(R.drawable.anzhuanghsibai);

        String url = dataBean.getImageUrl();
        viewHolder.imageview_item.setImageUrl(url,
                VolleyTool.getInstance(context).getImageLoader());

        return convertView;
    }

    class ViewHolder {
        NetworkImageView imageview_item;
        TextView textview_item;

        public ViewHolder(View view) {
            super();
            this.imageview_item = (NetworkImageView) view
                    .findViewById(R.id.imageview_item);
            this.textview_item = (TextView) view
                    .findViewById(R.id.textview_item);
        }

    }

}


VolleyTool

package com.example.saflyimage;  
import android.content.Context;  
import android.graphics.Bitmap;  
import android.support.v4.util.LruCache;  
import com.android.volley.RequestQueue;  
import com.android.volley.toolbox.ImageLoader;  
import com.android.volley.toolbox.ImageLoader.ImageCache;  
import com.android.volley.toolbox.Volley;  

public class VolleyTool {  
    //初始化请求队列、图片加载器  
    private RequestQueue queue;  
    private ImageLoader imageLoader;  

    //私有静态实例  
    private static VolleyTool instance;  
    //私有构造方法  
    private VolleyTool(Context context) {  
        //创建请求队列  
        queue = Volley.newRequestQueue(context);  
        //创建图片加载器  
        imageLoader = new ImageLoader(queue, new LruImageCache());  
    }  
    //公共、静态的方法  
    public static VolleyTool getInstance(Context context) {  
        if (instance == null) {  
            instance = new VolleyTool(context);  
        }  
        return instance;  
    }  

    //得到请求队列  
    public RequestQueue getQueue() {  
        return queue;  
    }  
    //得到图片加载器  
    public ImageLoader getImageLoader() {  
        return imageLoader;  
    }  

    /** 
     * 使用LRU回收算法的缓存类 
     */  
    class LruImageCache implements ImageCache {  

        // 缓存容器  
        private LruCache cache;  

        public LruImageCache() {  
            // 计算缓存的最值  
            int maxSize = (int) (Runtime.getRuntime().maxMemory() / 8);  
            //创建缓存对象实例  
            cache = new LruCache(maxSize) {  
                @Override  
                protected int sizeOf(String key, Bitmap value) {  
                    // 返回bitmap占用的内存大小  
                    return value.getRowBytes() * value.getHeight();  
                }  
            };  
        }  

        // 从缓存中取图片对象  
        @Override  
        public Bitmap getBitmap(String url) {  
            return cache.get(url);  
        }  

        // 将图片对象保存到缓存容器中  
        @Override  
        public void putBitmap(String url, Bitmap bitmap) {  
            cache.put(url, bitmap);  
        }  

    }  
}  

你可能感兴趣的:(Android网络操作,Android网络操作,networkIma)