我正在开发一个Android应用程序,它从服务器下载图像并将其显示在GridView
上。为此,我使用了扩展BaseAdapter
的适配器,其中我使用AsyncTask
来获取图像并在gridview中显示ti。代码如下。
public class CloudImageAdapter extends BaseAdapter {
private final String TAG = "CloudImageAdapter";
private Context context;
private ThumbnailCache mCache;
private LayoutInflater inflater;
private ArrayList<String> images = new ArrayList<String>();
ServerInfo server = null;
public CloudImageAdapter(Context context) {
this.context = context;
inflater = (LayoutInflater) this.context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// Pick cache size based on memory class of device
final ActivityManager am = (ActivityManager) this.context
.getSystemService(Context.ACTIVITY_SERVICE);
final int memoryClassBytes = am.getMemoryClass() * 1024 * 1024;
mCache = new ThumbnailCache(memoryClassBytes / 2);
server = ServerInfo.getServerInstance(context);
}
public void putImages(String imageName) {
images.add(imageName);
}
@Override
public int getCount() {
return images.size();
}
@Override
public Object getItem(int posotion) {
Log.i(TAG, "getItem() returns -> " + images.get(posotion));
return images.get(posotion);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View converView, ViewGroup parent) {
ImageView imageView;
if (converView == null) {
converView = inflater.inflate(R.layout.single_image_frame, null);
imageView = (ImageView) converView
.findViewById(R.id.singleImageFrame);
imageView.setImageBitmap(null);
imageView.setBackgroundResource(R.drawable.empty_photo);
} else {
imageView = (ImageView) converView;
}
final AsyncImageDecoder oldTask = (AsyncImageDecoder) imageView
.getTag();
if (oldTask != null) {
oldTask.cancel(false);
}
Bitmap bitmap = mCache.get(images.get(position));
if (bitmap == null) {
AsyncImageDecoder task = new AsyncImageDecoder(imageView);
task.execute(images.get(position));
imageView.setTag(task);
}
imageView.setImageBitmap(bitmap);
return converView;
}
class Holder {
ImageView frame;
}
/**
* Simple extension that uses {@link Bitmap} instances as keys, using their
* memory footprint in bytes for sizing.
*/
public static class ThumbnailCache extends
android.support.v4.util.LruCache<String, Bitmap> {
public ThumbnailCache(int maxSizeBytes) {
super(maxSizeBytes);
}
@Override
protected int sizeOf(String key, Bitmap data) {
return data.getByteCount();
}
}
class AsyncImageDecoder extends AsyncTask<String, Void, Bitmap> {
private String END = "End-Of-File";
private final WeakReference<ImageView> imageViewReference;
float rotation = 0;
public AsyncImageDecoder(ImageView frame) {
imageViewReference = new WeakReference<ImageView>(frame);
}
@Override
protected Bitmap doInBackground(String... imageName) {
Log.i(TAG, "AsyncImageDecoder::doInBackground() image -> "
+ imageName[0]);
Bitmap bitmap;
try {
bitmap = downloadImage(imageName[0]);
mCache.put(String.valueOf(imageName[0]), bitmap);
// rotation = getCameraPhotoOrientation(imagePath);
return bitmap;
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onPostExecute(Bitmap image) {
if (imageViewReference != null && image != null) {
final ImageView imageView = (ImageView) imageViewReference
.get();
if (imageView != null) {
/*
* if(image.getHeight() < image.getWidth())
* imageView.setRotation(90);
*/
imageView.setImageBitmap(image);
}
}
}
private Bitmap downloadImage(String path) throws IOException {
Bitmap thumb = null;
Socket socket = new Socket();
socket.connect(server.getServerAddress());
DataOutputStream out = new DataOutputStream(
socket.getOutputStream());
DataInputStream input = new DataInputStream(socket.getInputStream());
JSONObject header = new JSONObject();
JSONObject inner = new JSONObject();
try {
inner.put("command", "thumbnail");
inner.put("user", server.getUser());
inner.put("path", path);
header.put("header", inner);
} catch (JSONException e) {
e.printStackTrace();
}
out.write(header.toString().getBytes());
out.write(END.getBytes());
/*
* Reading thumbnails from the cloud
*/
byte[] temp = new byte[1024]; // Temporary byte array to read from
// the socket
byte[] store = null; // Reference variable to keep the byte array
int len = 0; // Length of the array
int receivedCount = 0;
while (true) {
receivedCount = input.read(temp);
if (receivedCount <= 0) {
thumb = decodeSampledBitmapFromUri(store, 50, 50);
/*
* thumb = BitmapFactory.decodeByteArray(store, 0,
* store.length);
*/
break; // Break when there is no more data to be read
}
byte[] buffer = new byte[len + receivedCount];
if (store != null) {
System.arraycopy(store, 0, buffer, 0, store.length);
System.arraycopy(temp, 0, buffer, len, receivedCount);
} else {
System.arraycopy(temp, 0, buffer, 0, receivedCount);
}
store = buffer;
len = len + receivedCount;
}
input.close();
out.close();
socket.close();
return thumb;
}
private Bitmap decodeSampledBitmapFromUri(byte[] data, int width,
int height) {
Bitmap bm = null;
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(data, 0, data.length, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, 140, 120);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
bm = BitmapFactory.decodeByteArray(data, 0, data.length, options);
return bm;
}
private int calculateInSampleSize(BitmapFactory.Options options,
int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
if (width > height) {
inSampleSize = Math.round((float) height
/ (float) reqHeight);
} else {
inSampleSize = Math.round((float) width / (float) reqWidth);
}
}
return inSampleSize;
}
}}
问题是当我在选项卡上运行此代码时,会下载大约30个图像。当我离开活动(没有完全加载图像)到任何其他活动时,应用程序等待,直到图像下载完成。当应用程序退出时,有没有办法立即停止所有AsyncTask
。
答案 0 :(得分:0)
在AsyncTask
的while循环内部,如果我们离开活动,请包含以下代码以提前退出循环:
if (isCancelled())
break;
然后使用
task.cancel(true);
在您活动的AsyncTask
事件中的onPause()
对象上,这会将isCancelled()
设置为true,并且会在您离开活动时暂停下载图片。
答案 1 :(得分:0)
您要做的是在Activity
在后台时暂停任务。下面的代码将暂停功能添加到AsyncTask
。
class AsyncImageDecoder extends AsyncTask<String, Void, Bitmap> {
private String END = "End-Of-File";
private final WeakReference<ImageView> imageViewReference;
float rotation = 0;
boolean resume = true;
boolean pause = false;
private String WATCH_DOG = "griffin";
public AsyncImageDecoder(ImageView frame) {
imageViewReference = new WeakReference<ImageView>(frame);
}
@Override
protected Bitmap doInBackground(String... imageName) {
Log.i(TAG, "AsyncImageDecoder::doInBackground() image -> "
+ imageName[0]);
Bitmap bitmap;
while(resume){
try {
bitmap = downloadImage(imageName[0]);
mCache.put(String.valueOf(imageName[0]), bitmap);
// rotation = getCameraPhotoOrientation(imagePath);
return bitmap;
} catch (IOException e) {
e.printStackTrace();
}
if(pause){ //This checks if the task has been paused and sleeps it till it has been notified to wake up
syncronized(WATCH_DOG){
try{
WATCH_DOG.wait();
} catch (InterruptedException e){e.printStackTrace();}
pause = false;
}
}
}
return null;
}
public void pauseTask(){
pause = true;
}
public void wakeUp(){
synchronized(WATCH_DOG){
WATCH_DOG.notify();
}
}
@Override
protected void onPostExecute(Bitmap image) {
if (imageViewReference != null && image != null) {
final ImageView imageView = (ImageView) imageViewReference
.get();
if (imageView != null) {
/*
* if(image.getHeight() < image.getWidth())
* imageView.setRotation(90);
*/
imageView.setImageBitmap(image);
}
}
}
private Bitmap downloadImage(String path) throws IOException {
Bitmap thumb = null;
Socket socket = new Socket();
socket.connect(server.getServerAddress());
DataOutputStream out = new DataOutputStream(
socket.getOutputStream());
DataInputStream input = new DataInputStream(socket.getInputStream());
JSONObject header = new JSONObject();
JSONObject inner = new JSONObject();
try {
inner.put("command", "thumbnail");
inner.put("user", server.getUser());
inner.put("path", path);
header.put("header", inner);
} catch (JSONException e) {
e.printStackTrace();
}
out.write(header.toString().getBytes());
out.write(END.getBytes());
/*
* Reading thumbnails from the cloud
*/
byte[] temp = new byte[1024]; // Temporary byte array to read from
// the socket
byte[] store = null; // Reference variable to keep the byte array
int len = 0; // Length of the array
int receivedCount = 0;
while (true) {
receivedCount = input.read(temp);
if (receivedCount <= 0) {
thumb = decodeSampledBitmapFromUri(store, 50, 50);
/*
* thumb = BitmapFactory.decodeByteArray(store, 0,
* store.length);
*/
break; // Break when there is no more data to be read
}
byte[] buffer = new byte[len + receivedCount];
if (store != null) {
System.arraycopy(store, 0, buffer, 0, store.length);
System.arraycopy(temp, 0, buffer, len, receivedCount);
} else {
System.arraycopy(temp, 0, buffer, 0, receivedCount);
}
store = buffer;
len = len + receivedCount;
}
input.close();
out.close();
socket.close();
return thumb;
}
private Bitmap decodeSampledBitmapFromUri(byte[] data, int width,
int height) {
Bitmap bm = null;
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(data, 0, data.length, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, 140, 120);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
bm = BitmapFactory.decodeByteArray(data, 0, data.length, options);
return bm;
}
private int calculateInSampleSize(BitmapFactory.Options options,
int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
if (width > height) {
inSampleSize = Math.round((float) height
/ (float) reqHeight);
} else {
inSampleSize = Math.round((float) width / (float) reqWidth);
}
}
return inSampleSize;
}
}}
在此之后,您需要在Activity
处于后台时添加更改,例如:
@Override
public void onPause(){
super.onPause();
task.pauseTask();
}
@Override
public void onResume(){
super.onResume();
task.wakeUp();
}
这应该意味着你离开它时不必完全破坏任务,当你回到它时它应该继续。