編輯:關於Android編程
Android異步加載的總結。除了LruCache,我們還可以使用DiskLruCache這個第三方的類來實現“二級緩存”。異步加載不僅僅是獲取網絡資源,我們可以加所有耗時的操作都看成異步加載,所有通過耗時的操作獲取的結果我們都可以通過緩存來提高效率,比如我們可以利用這裡的LruCache和DiskLruCache(這個緩存一般是用於緩存從網絡獲取的圖片,視頻等大的資源,這個時候我們一般和LruCache結合使用),使用Cache有個缺點,就是我們不能保證我們的數據是實時的,所以在realtime需求高的應用中,我們不應該使用緩存。而對於本地資源,我們很少用緩存的,就算是操作SQLite數據庫,我們也很少會用到LruCache,但是也有使用的。
listview的優化
1. 復用convertView,減少item view 的加載次數
2.使用holder,減少獲取item中子控件的次數
3.使用異步加載,防止阻塞主線程
4.使用google提供的LruCache類,將圖片緩存到內存中,減少從網絡獲取圖片的次數
加快速度,節省流量。lru 算法
5. 防止圖面緩存引起的錯位問題,給每個imageView添加一個tag,用URL做標識,加載圖片時
只有當前的URL和要加載圖片的imageView的tag中的URL相同時,才加載.
6.監聽listView的滾動狀態。滾動時停止記載,記錄當前可見item的起始和結束位置,並記錄他們的url,滾動結束後載再加載。 防止滑動中加載數據造成卡頓,和不必要的流量浪費.
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Handler;
import android.os.Message;
import android.util.LruCache;
import android.widget.ImageView;
import android.widget.ListView;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashSet;
import java.util.Set;
/**
* Created by Aldrich_jia on 2016-5-9.
*/
public class ImageLoader {
private ImageView mImageView;
private String iconUrl;
//創建cache
private LruCache mCaches;
private ListView mListView;
private Set mTask;
public ImageLoader(ListView mListView) {
this.mListView = mListView;
mTask = new HashSet<>();
//獲取最大可用內存
int maxMemory = (int) Runtime.getRuntime().maxMemory();
//設置換成大小值
int cacheSize = maxMemory / 4;
mCaches = new LruCache(cacheSize) {
//告訴系統,每次存入緩存多大
@Override
protected int sizeOf(String key, Bitmap value) {
//每次存入緩存時調用
return value.getByteCount();
}
};
}
//從緩存中獲取數據
public Bitmap getBitmapfromCache(String url) {
return mCaches.get(url);
}
//增加到緩存
private void addBitmaptoCache(String url, Bitmap bitmap) {
if (getBitmapfromCache(url) == null) {
mCaches.put(url, bitmap);
}
}
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (mImageView.getTag().equals(iconUrl)) {
mImageView.setImageBitmap((Bitmap) msg.obj);
}
}
};
public void showImageByThread(ImageView imageView, final String urlString) {
this.mImageView = imageView;
this.iconUrl = urlString;
new Thread(new Runnable() {
@Override
public void run() {
Bitmap mbitamp = getBitmapForURL(urlString);
Message message = Message.obtain();
message.obj = mbitamp;
mHandler.sendMessage(message);
}
}).start();
}
private Bitmap getBitmapForURL(String urlString) {
Bitmap mbitmap;
InputStream is = null;
try {
URL url = new URL(urlString);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
is = new BufferedInputStream(urlConnection.getInputStream());
mbitmap = BitmapFactory.decodeStream(is);
urlConnection.disconnect();
return mbitmap;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
public void showImageByAsync(ImageView imageView, String mUrl) {
//從緩存中取出對應的圖片
Bitmap bitmap = getBitmapfromCache(mUrl);
//如果緩存中沒有,必須去下載
if (bitmap == null) {
imageView.setImageResource(R.mipmap.ic_launcher);
// new NewsIconAsyncTask(imageView, mUrl).execute(mUrl);
} else {
imageView.setImageBitmap(bitmap);
}
}
/**
* 顯示從start到end中的圖片
*
* @param start
* @param end
*/
public void loadImages(int start, int end) {
for (int i = start; i < end; i++) {
String url = NewsAdapter.URLS[i];
//從緩存中取出對應的圖片
Bitmap bitmap = getBitmapfromCache(url);
//如果緩存中沒有,必須去下載
if (bitmap == null) {
NewsIconAsyncTask asyncTask = new NewsIconAsyncTask(url);
asyncTask.execute(url);
mTask.add(asyncTask);
} else {
ImageView imageView = (ImageView) mListView.findViewWithTag(url);
imageView.setImageBitmap(bitmap);
}
}
}
public void cancelAllTask() {
if (mTask != null) {
for (NewsIconAsyncTask task : mTask) {
task.cancel(false);
}
}
}
private class NewsIconAsyncTask extends AsyncTask {
// private ImageView mImageView;
private String mUrl;
public NewsIconAsyncTask(String mUrl) {
// this.mImageView = mImageView;
this.mUrl = mUrl;
}
@Override
protected Bitmap doInBackground(String... strings) {
String url = strings[0];
//從網絡上獲取圖片
Bitmap bitmap = getBitmapForURL(url);
if (bitmap != null) {
//將不在緩存的圖片加入緩存
addBitmaptoCache(url, bitmap);
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
ImageView imageView = (ImageView) mListView.findViewWithTag(mUrl);
if (imageView != null && bitmap != null) {
imageView.setImageBitmap(bitmap);
}
mTask.remove(this);
// if (mImageView.getTag().equals(mUrl)) {
// mImageView.setImageBitmap(bitmap);
//
// }
}
}
}
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import java.util.List;
/**
* Created by Aldrich_jia on 2016-5-9.
*/
public class NewsAdapter extends BaseAdapter implements AbsListView.OnScrollListener {
private List mList;
private LayoutInflater mLayoutInflater;
private ImageLoader mImageLoader;
private int mStart, mEnd;
public static String[] URLS;
private boolean mFirstIn;
public NewsAdapter(Context context, List mList, ListView listView) {
mLayoutInflater = LayoutInflater.from(context);
this.mList = mList;
mImageLoader = new ImageLoader(listView);
URLS = new String[mList.size()];
for (int i = 0; i < mList.size(); i++) {
URLS[i] = mList.get(i).newsIconUrl;
}
listView.setOnScrollListener(this);
mFirstIn = true;
}
@Override
public int getCount() {
return mList.size();
}
@Override
public Object getItem(int i) {
return mList.get(i);
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHoloder viewHoloder = null;
if (view == null) {
viewHoloder = new ViewHoloder();
view = mLayoutInflater.inflate(R.layout.item_layout, null);
viewHoloder.ivIcon = (ImageView) view.findViewById(R.id.iv_icon);
viewHoloder.tvTitle = (TextView) view.findViewById(R.id.tv_title);
viewHoloder.tvContent = (TextView) view.findViewById(R.id.tv_content);
view.setTag(viewHoloder);
} else {
viewHoloder = (ViewHoloder) view.getTag();
}
String iconUrl = mList.get(i).newsIconUrl;
viewHoloder.ivIcon.setTag(iconUrl);
viewHoloder.ivIcon.setImageResource(R.mipmap.ic_launcher);
// new ImageLoader().showImageByThread(viewHoloder.ivIcon,iconUrl);
mImageLoader.showImageByAsync(viewHoloder.ivIcon, iconUrl);
viewHoloder.tvTitle.setText(mList.get(i).newsTitle);
viewHoloder.tvContent.setText(mList.get(i).newsContent);
return view;
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == SCROLL_STATE_IDLE) {
//加載可見項
mImageLoader.loadImages(mStart, mEnd);
} else {
//停止任務
mImageLoader.cancelAllTask();
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
mStart = firstVisibleItem;
mEnd = firstVisibleItem + visibleItemCount;
//第一次顯示的時候調用
if (mFirstIn && visibleItemCount > 0) {
mImageLoader.loadImages(mStart, mEnd);
mFirstIn = false;
}
}
class ViewHoloder {
private TextView tvTitle, tvContent;
private ImageView ivIcon;
}
}
本文實例講解的是如何畫一個滿滿圓形水波紋loadingview,這類效果應用場景很多,比如內存占用百分比之類的,分享給大家供大家參考,具體內容如下效果圖如下:預備的知識:
在此鄭重聲明,貼出來的目的不是為了去破解人家的軟件,完全是一種學習的態度,不過好像通過這種方式也可以去漢化一些外國軟件。一、反編譯Apk得到Java源代碼首
實現更新下載進度的功能1. 通過廣播交互Server端將目前的下載進度,通過廣播的方式發送出來,Client端注冊此廣播的監聽器,當獲取到該廣播後,將廣播中當前的下載進度
概述ListView:一個可以垂直滑動的列表視圖。setEmptyView()接口繼承至ListView的父類AdapterView。可想而知,ListView為空時,才