此文,仅做为个人学习Android,记录成长以及方便复习!
本次是通过JSON获取页面数据,异步加载填充ListView
JSON地址:http://www.imooc.com/api/teacher?type=4&num=30
由于图片加载相对比较麻烦,首先第一步实现加载JSON中的标题和内容填充ListView
由于需要访问网络所以需要在清单文件(AndroidManifest.xml)中添加:
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
在布局文件Maintivity加载的布局文件activity_main.xml中添加LIstView
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ListView
android:id="@+id/listview"
android:layout_height="match_parent"
android:layout_width="match_parent"/>
</RelativeLayout>
添加一个布局文件(items_layout.xml)给自定义的适配器使用
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:gravity="center_vertical"
android:layout_marginBottom="10dp">
<ImageView
android:id="@+id/iv_icon"
android:layout_width="46dp"
android:layout_height="46dp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_marginLeft="10dp"
android:gravity="center"
>
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:textSize="20sp"
android:text="Title"/>
<TextView
android:id="@+id/tv_context"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="2"
android:text="context"/>
</LinearLayout>
</LinearLayout>
创建一个Bean对应适配器的布局文件,为AsynTask做准备
package com.rui.asynctaskdemo2;
/**
* 对应items_layout的Bean
*/
public class NewsBean {
private String iv_icon;
private String tv_title;
private String tv_context;
public String getIv_icon() {
return iv_icon;
}
public void setIv_icon(String iv_icon) {
this.iv_icon = iv_icon;
}
public String getTv_title() {
return tv_title;
}
public void setTv_title(String tv_title) {
this.tv_title = tv_title;
}
public String getTv_context() {
return tv_context;
}
public void setTv_context(String tv_context) {
this.tv_context = tv_context;
}
public NewsBean(String iv_icon, String tv_title, String tv_context) {
this.iv_icon = iv_icon;
this.tv_title = tv_title;
this.tv_context = tv_context;
}
public NewsBean(){
}
}
创建一个类继承BaseAdapter接口,创建成一个适配器
package com.rui.asynctaskdemo2;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.List;
public class NewsAdapter extends BaseAdapter{
private List<NewsBean> nlist;
private LayoutInflater inflater;
public NewsAdapter(Context context,List<NewsBean> data){
//数据源赋值给nlist
nlist = data;
//初始化局部对象
inflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
//显示数量是数据源的大小
return nlist.size();
}
@Override
public Object getItem(int i) {
//取出索引对应的数据项
return nlist.get(i);
}
@Override
public long getItemId(int i) {
//取出数据对应的索引
return i;
}
//返回每一项的显示内容
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHolder viewHolder=new ViewHolder();
//当view为空的时候
if(view == null){
//将layout转成View
view = inflater.inflate(R.layout.items_layout,null);
//组件ID存入viewHolder
viewHolder.iv_icon = view.findViewById(R.id.iv_icon);
viewHolder.tv_title = view.findViewById(R.id.tv_title);
viewHolder.tv_context = view.findViewById(R.id.tv_context);
//viewHolder存入view
view.setTag(viewHolder);
}else{//当View存在的时候,直接取出赋值给viewHolder
viewHolder = (ViewHolder) view.getTag();
}
//为view赋值
viewHolder.iv_icon.setImageResource(R.mipmap.ic_launcher);
viewHolder.tv_title.setText(nlist.get(i).getTv_title());
viewHolder.tv_context.setText(nlist.get(i).getTv_context());
return view;
}
//内部类,作用优化
class ViewHolder{
public TextView tv_title,tv_context;
public ImageView iv_icon;
}
}
在Maintivity.java中主要做了以下事情
1.创建一个内部类,继承AsynTask
2.创建一个方法,解析传入的InputStream转换为字符串
3.配置getJsonData方法,解析JSON成需要的数据
package com.rui.asynctaskdemo2;
import android.os.AsyncTask;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.ListView;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private ListView listView; //声明ListView
//json在线链接
private static String url="http://www.imooc.com/api/teacher?type=4&num=30";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//实例化ListView
listView = (ListView)findViewById(R.id.listview);
NewsAsyncTask nat = new NewsAsyncTask();
nat.execute(url);
}
//解析传入的URl
public List<NewsBean> getJsonData(String url){
List<NewsBean> newsBeanList = new ArrayList<NewsBean>();
try {
//获取JSON数据
String jsonString = readStream(new URL(url).openStream());
//Log.i("info",jsonString);打印是否能获取到JSON数据
//声明JSONBObject和NewsBean
JSONObject jsonObject;
NewsBean newsBean;
try {
//实例化JSONObject
jsonObject = new JSONObject(jsonString);
//获取数组节点data
JSONArray jsonArray = jsonObject.getJSONArray("data");
//循环出去数组中的子节点赋值给NewsBean
for(int i=0; i<jsonArray.length(); i++){
//获取数组中个每个子节点存入JSONObject
jsonObject = jsonArray.getJSONObject(i);
//实例化NewsBean
newsBean = new NewsBean();
//赋值
newsBean.setIv_icon(jsonObject.getString("picBig"));
newsBean.setTv_title(jsonObject.getString("name"));
newsBean.setTv_context(jsonObject.getString("description"));
//NewsBean加入集合
newsBeanList.add(newsBean);
}
} catch (JSONException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
//添加完成返回集合
return newsBeanList;
}
//解析字节流
@NonNull
private String readStream(InputStream is){
//初始化InputStreamReader、result
InputStreamReader isr;
StringBuffer result = new StringBuffer();
try {
//读取字符暂存
String line;
//字节流转字符流并设置编码为UTF-8
isr = new InputStreamReader(is,"utf-8");
//字符流转缓冲流
BufferedReader br = new BufferedReader(isr);
//循环趣数据存入result
while((line = br.readLine())!= null){
result.append(line);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return result.toString();
}
//内部类AsyncTask异步加载
public class NewsAsyncTask extends AsyncTask<String,Void,List<NewsBean>>{
@Override
protected List<NewsBean> doInBackground(String... strings) {
//获取传入的URL,通过getJsonData解析
return getJsonData(strings[0]);
}
@Override
protected void onPostExecute(List<NewsBean> newsBeans) {
super.onPostExecute(newsBeans);
//实例化NewsAdapter
NewsAdapter newsAdapter = new NewsAdapter(MainActivity.this,newsBeans);
//listView添加自定义适配器
listView.setAdapter(newsAdapter);
}
}
}
加载图像之---通过线程方式加载图像
添加一个用来加载图像的类ImageLoader.java
其中getBitmapFromUrl用来把图片URL解析成Bitmap
showImageByThread则是通过getBitmapFromUrl把bitmap传给Handler
最后通过Hander来显示图像
package com.rui.asynctaskdemo2;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.widget.ImageView;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
/**
* Created by qqazl001 on 2018-04-08..
* 处理图像的类
*/
public class ImageLoader {
//声明ImageView 接收showImageByThread传入的值
ImageView mimageView;
//用来判断mimageView中的getTag是否包含了url
String murl;
//接收线程发送的消息,通过Hanlder实现设置UI
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//判断mimageView中的getTag是否包含了url
if(mimageView.getTag().equals(murl)){
mimageView.setImageBitmap((Bitmap) msg.obj);
}
}
};
//把Bitmap传给Handler
public void showImagebyThread(final ImageView imageView, final String url){
new Thread(){
@Override
public void run() {
super.run();
mimageView = imageView;
murl = url;
//通过getBitmapFromUrl将url转成Bitmap
Bitmap bitmap = getBitmapFromUrl(url);
//创建一个message
Message message = Message.obtain();
//bitmap存入message
message.obj = bitmap;
//通过把存放了bitmap的message发送给Handler
mHandler.sendMessage(message);
}
}.start();
}
//通过图片的URL解析成Bitmap
public Bitmap getBitmapFromUrl(String urlString){
Bitmap bitmap;
InputStream is = null;
try {
//通过url获取图片的字节流
URL url = new URL(urlString);
HttpURLConnection connection= (HttpURLConnection) url.openConnection();
is = new BufferedInputStream(connection.getInputStream());
//通过Biteamp工程转成bitmap
bitmap = BitmapFactory.decodeStream(is);
//关闭connection
connection.disconnect();
return bitmap;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally{
//关闭流
if(is!=null){
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
}
把NewsAdapter.java的getView方法修改为,其实也就是把图像加载的类给加入了并传值
//返回每一项的显示内容
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHolder viewHolder=new ViewHolder();
//当view为空的时候
if(view == null){
//将layout转成View
view = inflater.inflate(R.layout.items_layout,null);
//组件ID存入viewHolder
viewHolder.iv_icon = view.findViewById(R.id.iv_icon);
viewHolder.tv_title = view.findViewById(R.id.tv_title);
viewHolder.tv_context = view.findViewById(R.id.tv_context);
//viewHolder存入view
view.setTag(viewHolder);
}else{//当View存在的时候,直接取出赋值给viewHolder
viewHolder = (ViewHolder) view.getTag();
}
viewHolder.iv_icon.setImageResource(R.mipmap.ic_launcher);
ImageView imageView = viewHolder.iv_icon;
String url = nlist.get(i).getIv_icon();
//用来解决异步加载错误的问题!
viewHolder.iv_icon.setTag(url);
//为view赋值
new ImageLoader().showImagebyThread(imageView,url);
viewHolder.tv_title.setText(nlist.get(i).getTv_title());
viewHolder.tv_context.setText(nlist.get(i).getTv_context());
return view;
}
加载图像之---通过AsynTask方式加载图像
添加一个用来加载图像的类ImageLoader.java
其中getBitmapFromUrl用来把图片URL解析成Bitmap
showImageByAsyncTask负责调用AsyncTask实现加载图像
package com.rui.asynctaskdemo2;
import android.content.AsyncTaskLoader;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.widget.ImageView;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
/**
* Created by qqazl001 on 2018-04-08..
* 处理图像的类
*/
public class ImageLoader {
//通过图片URL解析成Bitmap
public Bitmap getBitmapFromUrl(String urlString){
Bitmap bitmap;
InputStream is;
try {
//实例化URL类,将URL传入
URL url = new URL(urlString);
//打开链接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
//将图片url转成流
is = new BufferedInputStream(connection.getInputStream());
//将流转成Bitmap图像
bitmap = BitmapFactory.decodeStream(is);
//关闭链接
if(connection!=null) {
connection.disconnect();
}
//关闭流
if(is!=null){
is.close();
}
return bitmap;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
//通过AsyncTask异步加载图像
public void showImageByAsyntask(ImageView imageView,String url){
//实现异步加载类,并传值
new NewsAsynctask(imageView,url).execute(url);
}
//内部类,继承异步加载
class NewsAsynctask extends AsyncTask<String,Void,Bitmap>{
private ImageView mimageView;
private String murl;
//初始化参数
public NewsAsynctask(ImageView imageView,String url){
mimageView = imageView;
murl = url;
}
@Override
protected Bitmap doInBackground(String... strings) {
//通过getBitmapFromUrl方法,传入URL获取bitmap
return getBitmapFromUrl(strings[0]);
}
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
//判断图像的URL和传入的是否一致,一致则显示,解决显示跳动
if(mimageView.getTag().equals(murl)){
//为ImageView设置图像
mimageView.setImageBitmap(bitmap);
}
}
}
}
把NewsAdapter.java的getView方法修改为,其实也就是把图像加载的类给加入了并传值
//返回每一项的显示内容
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHolder viewHolder=new ViewHolder();
//当view为空的时候
if(view == null){
//将layout转成View
view = inflater.inflate(R.layout.items_layout,null);
//组件ID存入viewHolder
viewHolder.iv_icon = view.findViewById(R.id.iv_icon);
viewHolder.tv_title = view.findViewById(R.id.tv_title);
viewHolder.tv_context = view.findViewById(R.id.tv_context);
//viewHolder存入view
view.setTag(viewHolder);
}else{//当View存在的时候,直接取出赋值给viewHolder
viewHolder = (ViewHolder) view.getTag();
}
//为view赋值
//设置默认显示的图像
viewHolder.iv_icon.setImageResource(R.mipmap.ic_launcher);
viewHolder.tv_title.setText(nlist.get(i).getTv_title());
viewHolder.tv_context.setText(nlist.get(i).getTv_context());
//设置图像
ImageView mImageView = viewHolder.iv_icon;
String mUrl = nlist.get(i).getIv_icon();
//获取URL存入setTag,配合gettag 获取来匹配解决异步加载的错乱问题
mImageView.setTag(mUrl);
new ImageLoader().showImageByAsyntask(mImageView,mUrl);
return view;
}
为项目添加缓存(Lru)
1.初始化缓存,设置大小为可用内存的4分之1
2.添加2个方法,一个添加数据到缓存,一个取出
3.配置方法,在显示图像前判断缓存中是否存在,如果存在则直接使用缓存,不存在则加载并存入缓存
package com.rui.asynctaskdemo2;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.LruCache;
import android.widget.ImageView;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
/**
* Created by qqazl001 on 2018-04-08..
* 处理图像的类
*/
public class ImageLoader {
//声明缓冲
private LruCache<String,Bitmap> mLruCache;
public ImageLoader(){
//获取最大可用内存
int maxMemory = (int)Runtime.getRuntime().maxMemory();
//最大可用内存的4分之1
int cachesize = maxMemory / 4;
//实例化缓存类,并实现匿名内部类
mLruCache = new LruCache<String,Bitmap>(cachesize){
//匿名内部类
@Override
protected int sizeOf(String key, Bitmap value) {
//每次存入缓存时调用,查看Bitmap值的大小
return value.getByteCount();
}
};
}
//增加内容到缓存
public void addBitmapToCache(String url,Bitmap bitmap){
if(getBitmapFromUrl(url)==null){
mLruCache.put(url,bitmap);
}
}
//从缓存中读取
public Bitmap getBitmapFromCache(String url){
return mLruCache.get(url);
}
//通过图片URL解析成Bitmap
public Bitmap getBitmapFromUrl(String urlString){
Bitmap bitmap;
InputStream is;
try {
//实例化URL类,将URL传入
URL url = new URL(urlString);
//打开链接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
//将图片url转成流
is = new BufferedInputStream(connection.getInputStream());
//将流转成Bitmap图像
bitmap = BitmapFactory.decodeStream(is);
//关闭链接
if(connection!=null) {
connection.disconnect();
}
//关闭流
if(is!=null){
is.close();
}
return bitmap;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
//通过AsyncTask异步加载图像
public void showImageByAsyntask(ImageView imageView,String url){
//从缓存中获取图片
Bitmap bitmap = getBitmapFromCache(url);
if(bitmap==null){
//实现异步加载类,并传值
new NewsAsynctask(imageView,url).execute(url);
}else{
imageView.setImageBitmap(bitmap);
}
}
//内部类,继承异步加载
class NewsAsynctask extends AsyncTask<String,Void,Bitmap>{
private ImageView mimageView;
private String murl;
//初始化参数
public NewsAsynctask(ImageView imageView,String url){
mimageView = imageView;
murl = url;
}
@Override
protected Bitmap doInBackground(String... strings) {
Bitmap bitmap = getBitmapFromUrl(strings[0]);
if(bitmap!=null){
addBitmapToCache(strings[0],bitmap);
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
//判断图像的URL和传入的是否一致,一致则显示,解决显示跳动
if(mimageView.getTag().equals(murl)){
//为ImageView设置图像
mimageView.setImageBitmap(bitmap);
}
}
}
}
最后一步优化,滑动的时候不加载图像,让他开心的去滑,等滑动结束,再加载图像!
1.添加滑动的监听事件implements AbsListView.OnScrollListener
2.添加滑动加载滑动后可见项和滑动不加载的方法
滑动不加载的方法cancelAllTask()
停止滑动后加载图像的方法 loadImage()
3.添加解决首次启动不加载图像的逻辑
MainActivit.java当中NewsAsyncTask在适配器传入listView
//内部类AsyncTask异步加载
public class NewsAsyncTask extends AsyncTask<String,Void,List<NewsBean>>{
@Override
protected List<NewsBean> doInBackground(String... strings) {
//获取传入的URL,通过getJsonData解析
return getJsonData(strings[0]);
}
@Override
protected void onPostExecute(List<NewsBean> newsBeans) {
super.onPostExecute(newsBeans);
//实例化NewsAdapter
NewsAdapter newsAdapter = new NewsAdapter(MainActivity.this,newsBeans,listView);
//listView添加自定义适配器
listView.setAdapter(newsAdapter);
}
}
适配器NewsAdapter添加是监听事件
package com.rui.asynctaskdemo2;
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<NewsBean> nlist;
private LayoutInflater inflater;
private ImageLoader mimageLoader;
//设置一个布尔值,用来初始化界面时候,解决启动页面没有滑动不加载图像问题
private boolean mFirstIn;
//保存滑动后的第一项和最后一项
private int mStrat,mEnd;
//存放所有图片的URL
public static String[] URLS;
public NewsAdapter(Context context,List<NewsBean> data,ListView listView){
//数据源赋值给nlist
nlist = data;
//初始化局部对象
inflater = LayoutInflater.from(context);
//初始化图像加载类,在构造方法初始化,配合缓存
mimageLoader = new ImageLoader(listView);
//初始化数组=数据源大小
URLS = new String[data.size()];
//所有图片的URL存入URLS数组
for(int i=0;i<data.size();i++){
URLS[i] = data.get(i).getIv_icon();
}
//为ListView设置滑动监听事件
listView.setOnScrollListener(this);
//初始化为true,表示首次启动需要加载图像
mFirstIn = true;
}
@Override
public int getCount() {
//显示数量是数据源的大小
return nlist.size();
}
@Override
public Object getItem(int i) {
//取出索引对应的数据项
return nlist.get(i);
}
@Override
public long getItemId(int i) {
//取出数据对应的索引
return i;
}
//返回每一项的显示内容
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHolder viewHolder=new ViewHolder();
//当view为空的时候
if(view == null){
//将layout转成View
view = inflater.inflate(R.layout.items_layout,null);
//组件ID存入viewHolder
viewHolder.iv_icon = view.findViewById(R.id.iv_icon);
viewHolder.tv_title = view.findViewById(R.id.tv_title);
viewHolder.tv_context = view.findViewById(R.id.tv_context);
//viewHolder存入view
view.setTag(viewHolder);
}else{//当View存在的时候,直接取出赋值给viewHolder
viewHolder = (ViewHolder) view.getTag();
}
//为view赋值
//设置默认显示的图像
viewHolder.iv_icon.setImageResource(R.mipmap.ic_launcher);
viewHolder.tv_title.setText(nlist.get(i).getTv_title());
viewHolder.tv_context.setText(nlist.get(i).getTv_context());
//设置图像
ImageView mImageView = viewHolder.iv_icon;
String mUrl = nlist.get(i).getIv_icon();
//获取URL存入setTag,配合gettag 获取来匹配解决异步加载的错乱问题
mImageView.setTag(mUrl);
mimageLoader.showImageByAsyntask(mImageView,mUrl);
return view;
}
//滑动状态切换下调用
@Override
public void onScrollStateChanged(AbsListView absListView, int i) {
if(i == SCROLL_STATE_IDLE){
//停止状态加载可见项
mimageLoader.loadImage(mStrat,mEnd);
}else{
//停止任务
mimageLoader.cancelAllTask();
}
}
//滑动状态调用
@Override
public void onScroll(AbsListView absListView, int i, int i1, int i2) {
mStrat = i;//第一个可见元素
mEnd = i+i1;//第一个可见元素+可见元素长度=最后一个可见元素
//首次启动软件 mFirstIn为True且可见元素大于0个的时候,加载图像
if(mFirstIn && i1 >0){
mimageLoader.loadImage(mStrat,mEnd);
//设置为False,软件首次启动加载之后,次逻辑结束!
mFirstIn = false;
}
}
//内部类,作用优化
class ViewHolder{
public TextView tv_title,tv_context;
public ImageView iv_icon;
}
}
ImageLoader.java添加了加载可见项图像和取消加载方法
package com.rui.asynctaskdemo2;
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.MalformedURLException;
import java.net.URL;
import java.util.HashSet;
import java.util.Set;
/**
* Created by qqazl001 on 2018-04-08..
* 处理图像的类
*/
public class ImageLoader {
//初始化ListView
private ListView mlistView;
//把NewsAsynctask都存入一个集合,便于管理
private Set<NewsAsynctask> mtask;
//声明缓冲
private LruCache<String,Bitmap> mLruCache;
public ImageLoader(ListView listView){
mlistView = listView;
mtask = new HashSet<>();
//获取最大可用内存
int maxMemory = (int)Runtime.getRuntime().maxMemory();
//最大可用内存的4分之1
int cachesize = maxMemory / 4;
//实例化缓存类,并实现匿名内部类
mLruCache = new LruCache<String,Bitmap>(cachesize){
//匿名内部类
@Override
protected int sizeOf(String key, Bitmap value) {
//每次存入缓存时调用,查看Bitmap值的大小
return value.getByteCount();
}
};
}
//滑动的时候取消加载
public void cancelAllTask(){
//集合中有NewsAsyncTask,不为空
if(mtask != null){
//遍历取出其中的taks,并标记为false,便于调用销毁停止
for(NewsAsynctask task :mtask ){
task.cancel(false);
}
}
}
//滑动时加载图像
public void loadImage(int strat, int end){
//根据可见项获取设置图像
for(int i=strat;i<end;i++){
//从所有图像的UR'LS集合中依次取出存入url
String url = NewsAdapter.URLS[i];
//从缓存中获取图片
Bitmap bitmap = getBitmapFromCache(url);
//缓存中没有保存图像
if(bitmap==null){
//通过NewsAsynctask加载
NewsAsynctask task = new NewsAsynctask(url);
task.execute(url);
//并把NewsAsynctask存入集合,便于管理
mtask.add(task);
}else{
//通过Tag查找ListView中对应的 ImageView
ImageView imageView = mlistView.findViewWithTag(url);
//把从缓存中获取的bitmap设置到ImageView
imageView.setImageBitmap(bitmap);
}
}
}
//增加内容到缓存
public void addBitmapToCache(String url,Bitmap bitmap){
if(getBitmapFromUrl(url)==null){
mLruCache.put(url,bitmap);
}
}
//从缓存中读取
public Bitmap getBitmapFromCache(String url){
return mLruCache.get(url);
}
//通过图片URL解析成Bitmap
public Bitmap getBitmapFromUrl(String urlString){
Bitmap bitmap;
InputStream is;
try {
//实例化URL类,将URL传入
URL url = new URL(urlString);
//打开链接
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
//将图片url转成流
is = new BufferedInputStream(connection.getInputStream());
//将流转成Bitmap图像
bitmap = BitmapFactory.decodeStream(is);
//关闭链接
if(connection!=null) {
connection.disconnect();
}
//关闭流
if(is!=null){
is.close();
}
return bitmap;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
//通过AsyncTask异步加载图像
public void showImageByAsyntask(ImageView imageView,String url){
//从缓存中获取图片
Bitmap bitmap = getBitmapFromCache(url);
if(bitmap==null){
imageView.setImageResource(R.mipmap.ic_launcher);
}else{
imageView.setImageBitmap(bitmap);
}
}
//内部类,继承异步加载
class NewsAsynctask extends AsyncTask<String,Void,Bitmap>{
private ImageView mimageView;
private String murl;
//初始化参数
public NewsAsynctask(String url){
murl = url;
}
@Override
protected Bitmap doInBackground(String... strings) {
Bitmap bitmap = getBitmapFromUrl(strings[0]);
if(bitmap!=null){
addBitmapToCache(strings[0],bitmap);
}
return bitmap;
}
@Override
protected void onPostExecute(Bitmap bitmap) {
super.onPostExecute(bitmap);
// //判断图像的URL和传入的是否一致,一致则显示,解决显示跳动
// if(mimageView.getTag().equals(murl)){
// //为ImageView设置图像
// mimageView.setImageBitmap(bitmap);
// }
//从ListView获取ImageView
ImageView imageView = mlistView.findViewWithTag(murl);
//ImageVIew不为空和图像不为空的时候,为ImageView设置图像
if(imageView !=null && bitmap!=null){
imageView.setImageBitmap(bitmap);
}
//设置完图像之后,从mtask集合中移除
mtask.remove(this);
}
}
}