編輯:關於Android編程
今天來寫一個關於圖片請求的小例子,我們用NetworkImageView這個類來實現,這個類可以直接用在xml控件中,當作imageview,而且內部原理也是使用的ImageLoader,所以綜合性還是不錯的
效果圖如下:
本例就沒有再去進行封裝代碼了,封裝代碼在前幾篇中有寫到,下面2張圖是
返回的json格式的數據,本例也就從中獲取picSmall、name即可<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPjxpbWcgYWx0PQ=="這裡寫圖片描述" src="/uploadfile/Collfiles/20160727/20160727104958502.png" title="\" />
下面就是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源碼類
它裡面有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 LruCachecache; 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布局中
需要android:scaleType=”fitXY”
我這個demo沒有出現圖片錯亂的現象,有的朋友說會有錯亂的現象,我做了一個實驗,初始化有網絡,然後就關掉網絡,進行滑動依然是沒有問題的如下:
另外下載的圖片緩存到哪裡去了呢?如下
以下就是代碼區別############################
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 手機的時候,都會發現有些應用(例如 qq,微信,淘寶)為自己創建了賬號系統,並且能夠在設置頁面看到他,可是當自
最近從以前的項目中扒下來一個常用的模塊,在這裡有必要記錄一下的,就是android上獲取圖片以及裁剪圖片,怎麼樣?這個功能是不是很常用啊,你隨便打開一個Ap
概況 Android在4.3的版本中(即API 18)加入了NotificationListenerService,根據SDK的描述(AndroidDev
在本文當中,我將會與大家分享一個封裝了PopupWindow實現彈出菜單的類,並說明它的實現與使用。 因對界面的需求,android原生的彈出菜單已不能滿足我們的需求,自