您的位置:首页 > 移动开发 > Android开发

Android-单线程轮循机制批量下载图片、图片压缩、内存泄漏、图片缓存、文件缓存

2016-09-17 10:32 375 查看

ListView异步批量加载图片

单线程轮循机制批量下载图片

例如:imageloader框架底层也是这么实现的!

思路:主线程向任务集合添加一个任务,工作线程从任务集合移除第一个任务,如果有任务一直移除,一直轮循,拿到图片之后解析成Bitmap,呈现的imageView当中。



package com.tarena.musicclient.adapter;

import java.io.IOException;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.util.EntityUtils;

import com.tarena.musicclient.activity.R;
import com.tarena.musicclient.entity.Music;
import com.tarena.musicclient.util.BitmapUtils;
import com.tarena.musicclient.util.GlobalConsts;
import com.tarena.musicclient.util.HttpUtils;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

public class MusicAdapter extends BaseAdapter{
private Context context;
private List<Music> musics;
private LayoutInflater inflater;
//(2)声明任务集合
private List<ImageLoadTask> tasks=new ArrayList<ImageLoadTask>();
private ListView listView;
//声明用于轮循任务集合的工作线程
private Thread workThread;
//声明变量控制while循环
private boolean isLoop=true;
//声明缓存集合
private HashMap<String, SoftReference<Bitmap>> cache
=new HashMap<String, SoftReference<Bitmap>>();

//声明Handler  更新ImageView
private Handler handler=new Handler(){
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case HANDLER_LOAD_IMAGE_SUCCESS:
//给ImageView设置Bitmap
ImageLoadTask task=(ImageLoadTask)msg.obj;
//通过tag寻找到相应的ImageView
ImageView ivAlum=(ImageView)listView.findViewWithTag(task.position);
if(ivAlum!=null){
if(task.bitmap!=null){
ivAlum.setImageBitmap(task.bitmap);
}else{
ivAlum.setImageResource(R.drawable.ic_launcher);
}
}
break;
}
}
};

public static final int HANDLER_LOAD_IMAGE_SUCCESS=0;

public MusicAdapter(Context context, List<Music> musics, ListView listView) {
this.context=context;
this.musics=musics;
this.listView=listView;
inflater=LayoutInflater.from(context);
//(5)MusicAdapter有几个,工作线程就有几个
//对workThread进行初始化
workThread=new Thread(){
public void run() {
//(6)不断轮循任务集合
while(isLoop){
//如果任务集合不是空集
if(!tasks.isEmpty()){
//获取任务对象并且发送请求
ImageLoadTask task = tasks.remove(0);
//通过路径返回Bitmap对象
Bitmap bitmap=loadBitmap(task.path);
task.bitmap=bitmap;
//给相应的ImageView设置Bitmap   handler
Message msg=new Message();
msg.what=HANDLER_LOAD_IMAGE_SUCCESS;
msg.obj=task;
handler.sendMessage(msg);
}else{
//同步代码块:一但调用了某个对象的wait()/notify()方法后,外面一定套一个以这个对象为锁的同步代码块
synchronized (workThread) {
//如果任务集合是空集  wait等待
try {
workThread.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
};
workThread.start();
}

/**
* 通过path  获取Bitmap
* @param path
* @return
*/
public Bitmap loadBitmap(String path){
Bitmap bitmap=null;
String uri=GlobalConsts.BASEURL+path;
try {
//实体转成字节数组,字节数组转成图片
HttpEntity entity=HttpUtils.send(HttpUtils.METHOD_GET, uri, null);
byte[] bytes=EntityUtils.toByteArray(entity);
bitmap=BitmapUtils.loadBitmap(bytes, 50, 50);
//向缓存集合中存储缓存图片
cache.put(path, new SoftReference<Bitmap>(bitmap));

} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}

@Override
public int getCount() {
return musics.size();
}

public Object getItem(int position) {
return musics.get(position);
}

@Override
public long getItemId(int position) {
return position;
}

public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder=null;
if(convertView==null){
convertView=inflater.inflate(R.layout.item_lv_music, null);
holder=new ViewHolder();
holder.ivAlbum=(ImageView)convertView.findViewById(R.id.imageView1);
holder.tvName=(TextView)convertView.findViewById(R.id.tvName);
holder.tvDuration=(TextView)convertView.findViewById(R.id.tvDuration);
holder.tvSinger=(TextView)convertView.findViewById(R.id.tvSinger);
holder.tvAuthor=(TextView)convertView.findViewById(R.id.tvAuthor);
convertView.setTag(holder);
}
holder=(ViewHolder)convertView.getTag();
//给控件赋值
Music music=musics.get(position);
holder.tvName.setText(music.getName());
holder.tvSinger.setText(music.getSinger());
holder.tvAuthor.setText(music.getAuthor());
holder.tvDuration.setText(music.getDurationtime());
//给当前item中的ImageView设置一个Tag
//用于图片下载完成后根据该tag
//找到相应的ImageView
holder.ivAlbum.setTag(position);
//查询缓存中是否有图片 如果有 则直接获取
SoftReference<Bitmap> ref=cache.get(music.getAlbumpic());
if(ref!=null && ref.get()!=null){
Bitmap bitmap=ref.get();
holder.ivAlbum.setImageBitmap(bitmap);
System.out.println("从缓存中读取图片..");
return convertView;
}
//(3)下载一张图片
//向任务队列中添加一个图片任务
ImageLoadTask task=new ImageLoadTask();
//albumPic:   images/xxxxx.jpg
task.path=music.getAlbumpic();
task.position=position;
tasks.add(task);
//(4)唤醒工作线程  起来干活
notifyWorkThread();
return convertView;
}
/**
* 唤醒工作线程
*/
public void notifyWorkThread(){
//注意:一但调用wait活notify方法的时候,就要在这个同步代码块对象上加锁
synchronized (workThread) {
workThread.notify();
}
}

//(1)创建图片下载任务类型的类
class ImageLoadTask{
String path;//图片路径
Bitmap bitmap;//图片对象
int position;
}

class ViewHolder{
ImageView ivAlbum;
TextView tvName;
TextView tvDuration;
TextView tvSinger;
TextView tvAuthor;
}

public void stopWorkThread() {
isLoop=false;
notifyWorkThread();
}
}


图片压缩

图片压缩的意义:(像一些小图标,不需要很高清)

例如我们写的上面的程序图片都是从服务器端下载下来的,一个图片大小是5k,但是这个5k的图片加载到内存里就不止是5k了,一个Bitmap肯定比5k要多(5k的十倍)50k,10张就500k(半兆),这样图片多了的话就非常浪费内存,占用内存!当占用内存十分大的时候,android 手机就会出现GC(垃圾回收机制),自动销毁堆内存中的垃圾。如果java管理的内存越来越满,快溢出了,GC执行频率会上升,导致效果:在GC执行垃圾回收的时候,所有的线程暂停,主线程也不准绘制UI!如果GC执行频率非常频繁,肯定会出现吊帧,卡顿的现象!

Bitmap图片(位图对象):

BitmapFactory 图片工厂:

Options封装了创建Bitmap对象时使用的参数

package com.tarena.musicclient.adapter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.util.EntityUtils;

import com.tarena.musicclient.activity.R;
import com.tarena.musicclient.entity.Music;
import com.tarena.musicclient.util.BitmapUtils;
import com.tarena.musicclient.util.GlobalConsts;
import com.tarena.musicclient.util.HttpUtils;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

public class MusicAdapter extends BaseAdapter{
private Context context;
private List<Music> musics;
private LayoutInflater inflater;
//声明任务集合
private List<ImageLoadTask> tasks=new ArrayList<ImageLoadTask>();
private ListView listView;
//声明用于轮循任务集合的工作线程
private Thread workThread;
//声明Handler  更新ImageView
private Handler handler=new Handler(){
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case HANDLER_LOAD_IMAGE_SUCCESS:
//给ImageView设置Bitmap
ImageLoadTask task=(ImageLoadTask)msg.obj;
//通过tag寻找到相应的ImageView
ImageView ivAlum=(ImageView)listView.findViewWithTag(task.position);
if(ivAlum!=null){
if(task.bitmap!=null){
ivAlum.setImageBitmap(task.bitmap);
}else{
ivAlum.setImageResource(R.drawable.ic_launcher);
}
}
break;
}
}
};

public static final int HANDLER_LOAD_IMAGE_SUCCESS=0;

public MusicAdapter(Context context, List<Music> musics, ListView listView) {
this.context=context;
this.musics=musics;
this.listView=listView;
inflater=LayoutInflater.from(context);
//对workThread进行初始化
workThread=new Thread(){
public void run() {
//不断轮循任务集合
while(true){
//如果任务集合不是空集
if(!tasks.isEmpty()){
//获取任务对象并且发送请求
ImageLoadTask task = tasks.remove(0);
Bitmap bitmap=loadBitmap(task.path);
task.bitmap=bitmap;
//给相应的ImageView设置Bitmap   handler
Message msg=new Message();
msg.what=HANDLER_LOAD_IMAGE_SUCCESS;
msg.obj=task;
handler.sendMessage(msg);
}else{
synchronized (workThread) {
//如果任务集合是空集  wait等待
try {
workThread.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
};
workThread.start();
}

/**
* 通过path  获取Bitmap
* @param path
* @return
*/
public Bitmap loadBitmap(String path){
Bitmap bitmap=null;
String uri=GlobalConsts.BASEURL+path;
try {
HttpEntity entity=HttpUtils.send(HttpUtils.METHOD_GET, uri, null);
byte[] bytes=EntityUtils.toByteArray(entity);
/**
*图片压缩处理,工具类工具方法(传个来字节数字,和宽度、高度)
**/
bitmap=BitmapUtils.loadBitmap(bytes, 50, 50);
} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}

@Override
public int getCount() {
return musics.size();
}

public Object getItem(int position) {
return musics.get(position);
}

@Override
public long getItemId(int position) {
return position;
}

public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder=null;
if(convertView==null){
convertView=inflater.inflate(R.layout.item_lv_music, null);
holder=new ViewHolder();
holder.ivAlbum=(ImageView)convertView.findViewById(R.id.imageView1);
holder.tvName=(TextView)convertView.findViewById(R.id.tvName);
holder.tvDuration=(TextView)convertView.findViewById(R.id.tvDuration);
holder.tvSinger=(TextView)convertView.findViewById(R.id.tvSinger);
holder.tvAuthor=(TextView)convertView.findViewById(R.id.tvAuthor);
convertView.setTag(holder);
}
holder=(ViewHolder)convertView.getTag();
//给控件赋值
Music music=musics.get(position);
holder.tvName.setText(music.getName());
holder.tvSinger.setText(music.getSinger());
holder.tvAuthor.setText(music.getAuthor());
holder.tvDuration.setText(music.getDurationtime());
//给当前item中的ImageView设置一个Tag
//用于图片下载完成后根据该tag
//找到相应的ImageView
holder.ivAlbum.setTag(position);

//下载一张图片
//向任务队列中添加一个图片任务
ImageLoadTask task=new ImageLoadTask();
//albumPic:   images/xxxxx.jpg
task.path=music.getAlbumpic();
task.position=position;
tasks.add(task);
//唤醒工作线程  起来干活
notifyWorkThread();
return convertView;
}
/**
* 唤醒工作线程,起来运行跳出循环
*/
public void notifyWorkThread(){
synchronized (workThread) {
workThread.notify();
}
}

class ImageLoadTask{
String path;
Bitmap bitmap;
int position;
}

class ViewHolder{
ImageView ivAlbum;
TextView tvName;
TextView tvDuration;
TextView tvSinger;
TextView tvAuthor;
}
}


图片压缩工具类

package com.tarena.musicclient.util;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;

public class BitmapUtils {

/**
* 通过字节数组解析出Bitmap对象
* 需要按照一定的宽高的规格进行压缩
* @param bytes  数据源
* @param width  图片的目标宽度
* @param height  图片的目标高度
* @return
*/
public static Bitmap loadBitmap(byte[] bytes, int width, int height) {
Options opt=new Options();
//设置是否仅仅加载边界属性
opt.inJustDecodeBounds=true;
BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opt);
//获取图片的原始的高度与宽度
int w=opt.outWidth/width;
int h=opt.outHeight/height;
int scale=w>h ? w : h;
//设置压缩比例
opt.inSampleSize=scale;
//再次进行解析Bitmap
opt.inJustDecodeBounds=false;
return BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opt);
}

}


Android 内存泄漏

Android内存当中有垃圾对象,这些垃圾对象被占用了之后还不能被GC(垃圾回收机制回收)内存也不能重复利用,导致内存泄漏。

GC垃圾回收机制:



项目中内存泄漏中的地方:



解决方法:

在Activity生命周期方法中销毁的时候关闭当前线程,详情看上方代码

内存泄漏最常见的情况:

Thread

new Thread (){}.start()必须给出run方法执行完毕的条件,在应用程序退出的时候销毁工作线程。

查看本程序中运行的线程



Java中的引用

强引用: StrongReference

e=new Emp();

就算出OOM,也不会销毁强引用

软引用: SoftReference

弱java管理的内存接近阈值,将会销毁一些软引用。释放内存

弱引用: WeakReference

就算java管理的内存没有接近阈值,就会销毁一些弱引用。

虚引用: …………

由GC管理的。

软引用的使用:

SoftReference s=new SoftReference(bitmap);

Bitmap bitmap=s.get();

Android图片的内存缓存

第一次把图片下载到手机后,存入内存中,再次需要下载图片时,先去内存中查询,如果已经下载过,那么直接获取,如果没有获取过,再去下载。

存:

注意:

一直存会容易c内存溢出OOM

HashMap < String,Bitmap > cache ;

cache.put(“images/jsjs.jpg”,bitmap);

cache.put(“images/jsjs.jpg”,bitmap);

cache.put(“images/jsjs.jpg”,bitmap);

cache.put(“images/jsjs.jpg”,bitmap);

cache.put(“images/jsjs.jpg”,bitmap);

WeakHashMap:

弱引用,当java的内存达到阈值的时候,会随机删除键值对。

取:

Bitmap bitmap=cache.get(“images/jsjs.jpg”);

改进后:

HashMap < String,SoftReference> map;

map.put(path,new SoftReference(bitmap));

map.get(path).get();

代码参考上方例子

图片的文件缓存

(1)下载图片后,把图片数据保存到应用的缓存目录中。

public void save(File targetFile,Bitmap bitmap)//工具类存的方法

Bitmap bitmap;

FileOutputStream fos;//写出到文件

file.write();

//缓存目录都存到cach文件中

bimap.compress();//压缩方法

(2)再次获取图片时,先去内存缓存中去查询,如果没有则去缓存目录中查询。有则直接读取。没有的话再次发送请求。

public Bitmap loadBitmap(path)//工具类方法:通过路径加载bitmap,也可以出入压缩的比例

String path;

BitmapFactory.decodeFile(path,Options);

文件缓存工具类方法:

package com.tarena.musicclient.util;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;

public class BitmapUtils {

/**
* 通过一个文件路径  查找到Bitmap
* @param path
* @return
* @throws IOException
*/
public static Bitmap  loadBitmap(String path)throws IOException{
File file=new File(path);
if(file.exists()){
return BitmapFactory.decodeFile(path);
}
return null;
}

/***
* 保存图片
* @param targetFile  目标文件
* @param bitmap  位图对象
* @throws IOException
*/
public static void save(File targetFile, Bitmap bitmap)throws IOException{
if(!targetFile.getParentFile().exists()){
//父目录不存在 则创建
targetFile.getParentFile().mkdirs();
}
if(!targetFile.exists()){
targetFile.createNewFile();
}
//写入
FileOutputStream fos=new FileOutputStream(targetFile);
bitmap.compress(CompressFormat.JPEG, 100, fos);
}

/**
* 通过字节数组解析出Bitmap对象
* 需要按照一定的宽高的规格进行压缩
* @param bytes  数据源
* @param width  图片的目标宽度
* @param height  图片的目标高度
* @return
*/
public static Bitmap loadBitmap(byte[] bytes, int width, int height) {
Options opt=new Options();
//设置是否仅仅加载边界属性
opt.inJustDecodeBounds=true;
BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opt);
//获取图片的原始的高度与宽度
int w=opt.outWidth/width;
int h=opt.outHeight/height;
int scale=w>h ? w : h;
//设置压缩比例
opt.inSampleSize=scale;
//再次进行解析Bitmap
opt.inJustDecodeBounds=false;
return BitmapFactory.decodeByteArray(bytes, 0, bytes.length, opt);
}

}


使用:

package com.tarena.musicclient.adapter;

import java.io.File;
import java.io.IOException;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.util.EntityUtils;

import com.tarena.musicclient.activity.R;
import com.tarena.musicclient.entity.Music;
import com.tarena.musicclient.util.BitmapUtils;
import com.tarena.musicclient.util.GlobalConsts;
import com.tarena.musicclient.util.HttpUtils;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

public class MusicAdapter extends BaseAdapter{
private Context context;
private List<Music> musics;
private LayoutInflater inflater;
//声明任务集合
private List<ImageLoadTask> tasks=new ArrayList<ImageLoadTask>();
private ListView listView;
//声明用于轮循任务集合的工作线程
private Thread workThread;
//声明变量控制while循环
private boolean isLoop=true;
//声明缓存集合
private HashMap<String, SoftReference<Bitmap>> cache
=new HashMap<String, SoftReference<Bitmap>>();

//声明Handler  更新ImageView
private Handler handler=new Handler(){
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case HANDLER_LOAD_IMAGE_SUCCESS:
//给ImageView设置Bitmap
ImageLoadTask task=(ImageLoadTask)msg.obj;
//通过tag寻找到相应的ImageView
ImageView ivAlum=(ImageView)listView.findViewWithTag(task.position);
if(ivAlum!=null){
if(task.bitmap!=null){
ivAlum.setImageBitmap(task.bitmap);
}else{
ivAlum.setImageResource(R.drawable.ic_launcher);
}
}
break;
}
}
};

public static final int HANDLER_LOAD_IMAGE_SUCCESS=0;

public MusicAdapter(Context context, List<Music> musics, ListView listView) {
this.context=context;
this.musics=musics;
this.listView=listView;
inflater=LayoutInflater.from(context);
//对workThread进行初始化
workThread=new Thread(){
public void run() {
//不断轮循任务集合
while(isLoop){
//如果任务集合不是空集
if(!tasks.isEmpty()){
//获取任务对象并且发送请求
ImageLoadTask task = tasks.remove(0);
Bitmap bitmap=loadBitmap(task.path);
task.bitmap=bitmap;
//给相应的ImageView设置Bitmap   handler
Message msg=new Message();
msg.what=HANDLER_LOAD_IMAGE_SUCCESS;
msg.obj=task;
handler.sendMessage(msg);
}else{
synchronized (workThread) {
//如果任务集合是空集  wait等待
try {
workThread.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
};
workThread.start();
}

/**
* 通过path  获取Bitmap
* @param path
* @return
*/
public Bitmap loadBitmap(String path){
Bitmap bitmap=null;
String uri=GlobalConsts.BASEURL+path;
try {
HttpEntity entity=HttpUtils.send(HttpUtils.METHOD_GET, uri, null);
byte[] bytes=EntityUtils.toByteArray(entity);
bitmap=BitmapUtils.loadBitmap(bytes, 50, 50);
//向缓存集合中存储缓存图片
cache.put(path, new SoftReference<Bitmap>(bitmap));
//向文件缓存中存储图片
//cacheDir:  /data/data/com.xxx.client/cache/
//path: images/xxxx.jpg
File targetFile=new File(context.getCacheDir(), path);
BitmapUtils.save(targetFile, bitmap);

} catch (IOException e) {
e.printStackTrace();
}
return bitmap;
}

@Override
public int getCount() {
return musics.size();
}

public Object getItem(int position) {
return musics.get(position);
}

@Override
public long getItemId(int position) {
return position;
}

public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder=null;
if(convertView==null){
convertView=inflater.inflate(R.layout.item_lv_music, null);
holder=new ViewHolder();
holder.ivAlbum=(ImageView)convertView.findViewById(R.id.imageView1);
holder.tvName=(TextView)convertView.findViewById(R.id.tvName);
holder.tvDuration=(TextView)convertView.findViewById(R.id.tvDuration);
holder.tvSinger=(TextView)convertView.findViewById(R.id.tvSinger);
holder.tvAuthor=(TextView)convertView.findViewById(R.id.tvAuthor);
convertView.setTag(holder);
}
holder=(ViewHolder)convertView.getTag();
//给控件赋值
Music music=musics.get(position);
holder.tvName.setText(music.getName());
holder.tvSinger.setText(music.getSinger());
holder.tvAuthor.setText(music.getAuthor());
holder.tvDuration.setText(music.getDurationtime());
//给当前item中的ImageView设置一个Tag
//用于图片下载完成后根据该tag
//找到相应的ImageView
holder.ivAlbum.setTag(position);
Bitmap bitmap=getCacheBitmap(music.getAlbumpic());
if(bitmap!=null){
holder.ivAlbum.setImageBitmap(bitmap);
return convertView;
}
//下载一张图片
//向任务队列中添加一个图片任务
ImageLoadTask task=new ImageLoadTask();
//albumPic:   images/xxxxx.jpg
task.path=music.getAlbumpic();
task.position=position;
tasks.add(task);
//唤醒工作线程  起来干活
notifyWorkThread();
return convertView;
}

private Bitmap getCacheBitmap(String path){
//查询缓存中是否有图片 如果有 则直接获取
SoftReference<Bitmap> ref=cache.get(path);
if(ref!=null && ref.get()!=null){
Bitmap bitmap=ref.get();
System.out.println("从缓存中读取图片..");
return bitmap;
}
//查询文件缓存
File targetFile=new File(context.getCacheDir(), path);
Bitmap bitmap;
try {
bitmap = BitmapUtils.loadBitmap(targetFile.getAbsolutePath());
//如果文件中查到了bitmap
//那么存入内存缓存
if(bitmap!=null){
System.out.println("从文件缓存中读取图片..");
cache.put(path, new SoftReference<Bitmap>(bitmap));
}
return bitmap;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}

/**
* 唤醒工作线程
*/
public void notifyWorkThread(){
synchronized (workThread) {
workThread.notify();
}
}

class ImageLoadTask{
String path;
Bitmap bitmap;
int position;
}

class ViewHolder{
ImageView ivAlbum;
TextView tvName;
TextView tvDuration;
TextView tvSinger;
TextView tvAuthor;
}

public void stopWorkThread() {
isLoop=false;
notifyWorkThread();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: