转载请说明出处,欢迎转载。http://write.blog.csdn.net/postedit/51533261
本篇博客总结了慕课网关于异步加载图片的知识要点,和大家一起分享,有感觉听得不连贯的可以来看看。
看完本篇博客,你将学习到下面的知识:
1.怎样将一个url(也可以说是一个InputStream)转换为一个json字符串信息。
2.怎样运用插件写一个我认为完美的model类来为解析json做准备。
3.AsyncTask的基本用法。
4.Gosn的基本用法。
5.Adapter的常用优化写法。
6.通过LruCache缓存已经加载的图片。
7.listview高效加载复杂item布局。
8.编写json实体类的AS小插件。
好了,直接上代码,代码里面有详细的解释。
package com.robin.loadimageinlistview;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ListView;
import com.google.gson.Gson;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private ListView listView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) findViewById(R.id.lv_main);
String URL1 = "http://www.imooc.com/api/teacher?type=4&num=30";
new MyAsyncTask().execute(URL1);
}
class MyAsyncTask extends AsyncTask> {//(知识点3)
@Override
protected List doInBackground(String... params) {
return getJsonData(params[0]);
}
@Override
protected void onPostExecute(List beanDatas) {
super.onPostExecute(beanDatas);
NewsAdapter adapter = new NewsAdapter(MainActivity.this, beanDatas, listView);
listView.setAdapter(adapter);
}
}
/**
* 通过URL获取json字符串(知识点2)
*
* @param url
* @return List
*/
private List getJsonData(String url) {
String jsonString = null;
try {
jsonString = readStream(new URL(url).openStream());
} catch (IOException e) {
e.printStackTrace();
}
Gson gson = new Gson();
if(jsonString==null||"".equals(jsonString))return null;//如果jsonString返回有问题,就不解析了。
NewsBean newsBean = gson.fromJson(jsonString, NewsBean.class);//(知识点4)需要将Gosn的包导入进project中。怎么导,就不详细说了,去Google
return newsBean.getData();
}
/**
* 怎样将一个url(也可以说是一个InputStream)转换为一个json字符串信息。(知识点1)
*
* @param is
* @return String
*/
private String readStream(InputStream is) {
String result = "";
InputStreamReader isr;
String line;
try {
isr = new InputStreamReader(is, "utf-8");//字节流转化为字符流
BufferedReader br = new BufferedReader(isr);
while ((line = br.readLine()) != null) {
result += line;
}
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
}
package com.robin.loadimageinlistview;
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;
public class NewsAdapter extends BaseAdapter implements AbsListView.OnScrollListener{
private List newsBeans;
private LayoutInflater mInflater;
private ImageLoader imageLoader;
private int mStart,mEnd;
public static String[] URLS;//存放要加载的图片的url
private boolean isFirst = false;//控制第一次进入listview的时候加载数据
public NewsAdapter(Context context, List newsBeans, ListView listView) {//初始化数据
this.newsBeans = newsBeans;
this.mInflater = LayoutInflater.from(context);
imageLoader = new ImageLoader(listView);// 确保只有一个LruCache
URLS = new String[newsBeans.size()];
for (int i=0;i(知识点7)
if(scrollState==SCROLL_STATE_IDLE){//停止滚动,加载可见项
imageLoader.loadImage(mStart,mEnd);
}else{//停止加载
imageLoader.cancelAllTask();
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {//整个滑动的时候都会调用
mStart = firstVisibleItem;//第一个可见元素
mEnd =firstVisibleItem+visibleItemCount;//最后一个可见元素=第一个可见元素+可见元素的数量
if(isFirst && visibleItemCount > 0){//第一次加载的时候调用,显示图片
imageLoader.loadImage(mStart,mEnd);
isFirst=false;
}
}
class ViewHolder{
public TextView tvTitle;
public TextView tvContent;
public ImageView ivIcon;
}
}
对
知识点7的一点解释,当item布局非常复杂的时候,这是用户区频繁滚动listview,listview会频繁调用getView方法去获取item,导致卡顿,然而,平常的使用过程中,我们发现一般用户滚动的时候不太注意内容,停止滚动的时候才回去看内容,因此我们考虑如果将显示内容的权利从getView中移交给滚动事件处理的话,这个问题就能得到解决。
接下来上最重要的控制图片缓存以及加载的类
package com.robin.loadimageinlistview;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
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.URL;
import java.util.HashSet;
import java.util.Set;
public class ImageLoader {
private LruCache cache;//用于缓存图片
private ListView listView;
private Set mTask;//管理AsyncTask
public ImageLoader(ListView listView) {//初始化一些数据
this.listView = listView;
this.mTask = new HashSet<>();
int maxMemry = (int) Runtime.getRuntime().maxMemory();//获取当前应用可用的最大内存
int cacheSize = maxMemry/4;//以最大的四分之一作为可用的缓存大小
this.cache = new LruCache(cacheSize){//初始化LruCache
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getByteCount();//每次存入缓存的大小,即bitmap的大小
}
};
}
/**
* 将内容保存到LruCache
* @param url
* @param bitmap
*/
public void addBitmapToCache(String url,Bitmap bitmap){
if(getBitmapFromCache(url)==null){//如果没有保存的话就保存。
cache.put(url,bitmap);
}
}
/**
* 从LruCache中获取bitmap
* @param url
* @return Bitmap
*/
public Bitmap getBitmapFromCache(String url){
return this.cache.get(url);
}
/**
* 将图片url转化为bitmap
* @param urlString
* @return Bitmap
*/
public Bitmap getBitmapFromUrl(String urlString){
Bitmap bitmap;
InputStream is=null;
try {
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
is = new BufferedInputStream(connection.getInputStream());
bitmap = BitmapFactory.decodeStream(is);
connection.disconnect();
return bitmap;
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(is!=null){
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
public void showImageByAsyncTask(ImageView imageView,String url){//改进之后,获取图片的控制权由原来getview改成了滚动状态。
Bitmap bitmap = getBitmapFromCache(url);//从缓存中获取图片
if(bitmap==null){//如果没有就设置默认的图片
imageView.setImageResource(R.mipmap.ic_launcher);
}else{//如果有就设置当前的图片
imageView.setImageBitmap(bitmap);
}
}
private class NewsAsyncTask extends AsyncTask{
private String url;
public NewsAsyncTask(String url) {
this.url = url;
}
@Override
protected Bitmap doInBackground(String... params) {
String url = params[0];
Bitmap bitmap = getBitmapFromUrl(url);//获取网络图片
if(bitmap!=null){
addBitmapToCache(url,bitmap); //将不在缓存的图片加载的缓存中去
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
ImageView imageView =(ImageView) listView.findViewWithTag(url);
if(imageView!=null&&bitmap!=null){//判断这个url所对应的imageview是否对应,对应的话才设置图片,
imageView.setImageBitmap(bitmap);
}
}
}
/**
* 加载从start到end的所有图片
* @param start
* @param end
*/
public void loadImage(int start,int end){
for (int i= start;i
https://github.com/zzz40500/GsonFormat
好了,大概就这些了,上传一张效果图
最后感谢大家,喜欢请点赞,有疑问,可以回复交流,有错误,请指出。Thx。
阿斯顿