最近看了慕课网的教学视频,这里记录一下学习笔记.
学习视频地址:http://www.imooc.com/learn/406
视频完成的小例子很简单,就是展示一个带图片的列表.如下图所示:
首先把MainActivity的布局,ListView的Item布局 listView要用的Adapter写好,这个代码很简单就不贴了.
然后从网上获取数据并解析.请求数据的网址为:http://www.imooc.com/api/teacher?type=4&num=30 获取到的数据为Json格式.对应的网络请求和数据解析在NewsUtil.java中完成
public class NewsUtil {
/**
* 读取流中的字符串 ada
*
* @param is
* @return
*/
public static String readStream(InputStream is) {
StringBuilder sb = new StringBuilder();
try {
InputStreamReader isr = new InputStreamReader(is, "utf-8");
BufferedReader br = new BufferedReader(isr);
String line = "";
while ((line = br.readLine()) != null) {
sb.append(line);
}
} catch (Exception e) {
e.printStackTrace();
}
return sb.toString();
}
/**
* 解析json字符串 ada
*
* @param url
* @return
*/
public static List<NewsInfo> getJsonData(String url) {
List<NewsInfo> datas = new ArrayList<NewsInfo>();
try {
InputStream inputStream = new URL(url).openStream();
String jsonString = readStream(inputStream);
Log.e("ada", jsonString);
JSONObject jsonObject = new JSONObject(jsonString);
JSONArray jsonArray = jsonObject.getJSONArray("data");
for (int i = 0; i < jsonArray.length(); i++) {
JSONObject object = jsonArray.getJSONObject(i);
NewsInfo newsInfo = new NewsInfo();
newsInfo.title = object.getString("name");
newsInfo.content = object.getString("description");
newsInfo.url = object.getString("picSmall");
datas.add(newsInfo);
}
} catch (Exception e) {
e.printStackTrace();
}
Log.e("ada", "datas size:"+datas.size());
return datas;
}
}
readStream()方法根据请求的链接拿到对应的json字符串
getJsonData()解析json字符串并封装好供listView使用
解析Json字符串是要创建对应的javaBean文件NewsInfo.java
NewsInfo.java
/**
* 新闻列表结构体
*
* @author ada 2016年10月8日
*
*/
public class NewsInfo {
public String title;/**标题**/
public String content;/**内容**/
public String url;/**图片的下载地址**/
}
然后在MainActivity中进行异步加载,获取数据成功后,刷新界面,展示列表.(此时还未对图片进行加载,使用的默认图)异步加载使用的AsyncTask
private class MyAsyncTask extends AsyncTask<String, Void, List<NewsInfo>> {
@Override
protected List<NewsInfo> doInBackground(String... params) {
// 子线程中获取解析数据
return NewsUtil.getJsonData(params[0]);
}
@Override
protected void onPostExecute(List<NewsInfo> result) {
super.onPostExecute(result);
// 主线程中刷新页面
lv.setAdapter(new NewsAdapter(MainActivity.this, result,lv));
}
}
接下来对来写列表中的图片加载方法,首先在NewsUtil中增加获取图片的方法getBitmapFromURL
public static Bitmap getBitmapFromURL(String path) {
InputStream is = null;
Bitmap bitmap;
try {
is = new URL(path).openStream();
bitmap = BitmapFactory.decodeStream(is);
return bitmap;
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (is != null)
is.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
然后新建类ImageLoder类,在里面处理图片加载逻辑,并对图片加载进行优化管理
ImageLoder中主要做了这几件事:
1. 异步加载网络图片(thread或asyncTask皆可)
2. 利用LruCache提高用户体验,优化ListView图片加载
3. 改造加载逻辑,进一步优化ListView加载 滑动时停止加载,停止时加载可见项
- 异步加载网络图片(thread或asyncTask皆可)对应的代码
private class ImageAsyncTask extends AsyncTask<String, Void, Bitmap> {
private String url;
public ImageAsyncTask(String url) {
this.url = url;
}
@Override
protected Bitmap doInBackground(String... params) {
String backGroundUrl = params[0];
Bitmap bitmap = NewsUtil.getBitmapFromURL(backGroundUrl);
//添加图片到缓存
if (bitmap != null) {
addBitmapToLru(url, bitmap);
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap result) {
super.onPostExecute(result);
mImageView = (ImageView) listView.findViewWithTag(url);
if (mImageView != null && result != null) {
mImageView.setImageBitmap(result);
}
mTasks.remove(this);
}
}
2. 利用LruCache提高用户体验,优化ListView图片加载
// 初始化LeruCache
int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 4);
lruCache = new LruCache<String, Bitmap>(maxMemory) {
@Override
protected int sizeOf(String key, Bitmap value) {
// 每次存入缓存的时候调用,返回存入对象的大小。
return value.getByteCount();
}
};
/**
* 添加图片到缓存
* ada
* @param key
* @param value
*/
public void addBitmapToLru(String key, Bitmap value) {
if (getBitmapFromLru(key) == null) {
lruCache.put(key, value);
}
}
/**
* 从缓存中获取图片
* ada
* @param key
* @return
*/
public Bitmap getBitmapFromLru(String key) {
return lruCache.get(key);
}
- 改造加载逻辑,进一步优化ListView加载 滑动时停止加载,停止时加载可见项
Adapter实现方法OnScrollListener
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == SCROLL_STATE_IDLE) {
//加载可见项
imageLoader.loadImages(mStart,mEnd);
}else {
//停止加载所有
imageLoader.cacelAllTask();
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
mStart = firstVisibleItem;
mEnd = firstVisibleItem + visibleItemCount;
//处理预加载
if (mFrist && visibleItemCount > 0) {
imageLoader.loadImages(mStart, mEnd);
mFrist = false;
}
ImageLode中增加对应的loadImages()和cacelAllTask()
/**
* 根据起始位置加载指定图片
* ada
* @param mStart
* @param mEnd
*/
public void loadImages(int mStart, int mEnd) {
for (int i = mStart; i < mEnd; i++) {
String url = NewsAdapter.URLS[i];
Bitmap bitmap = getBitmapFromLru(url);
if (bitmap == null) {
ImageAsyncTask asyncTask = new ImageAsyncTask(url);
asyncTask.execute(url);
mTasks.add(asyncTask);
} else {
mImageView = (ImageView) listView.findViewWithTag(url);
mImageView.setImageBitmap(bitmap);
}
}
}
public void cacelAllTask() {
if (mTasks != null) {
for (ImageAsyncTask task : mTasks) {
task.cancel(false);
}
}
}