简述:
这种jvm无法及时回收avtivity的情况,源于有消息再队列中,handler无法回收,所以如果handler非静态的那么使用handler的Activity和Service就无法回收
转自 http://www.eoeandroid.com/thread-184245-1-1.html 的解决方法
package com.anialy.testproj.part1.activity;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.util.WeakHashMap;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import com.anialy.testproj.R;
import com.anialy.testproj.R.id;
import com.anialy.testproj.R.layout;
import com.anialy.testproj.R.menu;
import com.anialy.testproj.part1.util.HttpUtil;
public class MainActivity extends Activity implements View.OnClickListener {
private static final String TAG = "MainActivity";
private static final int IMAGE_FAILURE = 0x0;
private static final int IMAGE_SUCCESS = 0x1;
private Activity context;
/**
* 定义控件
*/
private Button btn;
private ImageView iv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context = this;
setContentView(R.layout.activity_main);
initWidgets();
}
private void initWidgets(){
btn = (Button) findViewById(R.id.btn);
iv = (ImageView) findViewById(R.id.iv);
//设置监听
btn.setOnClickListener(this);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public void onClick(View v) {
switch(v.getId()){
case R.id.btn:
Log.i(TAG, "now get image !");
new Thread(){
public void run() {
Log.i(TAG, "run !");
// 检测sd卡是否插入
String status = Environment.getExternalStorageState();
if (status.equals(Environment.MEDIA_MOUNTED)) {
Log.i(TAG, "sd in !");
String url = "http://192.168.2.199:8080/FileServer/fetch?id=Ud1VjGHmNGJ8Lpyu2";
InputStream is = HttpUtil.getInputStreambyURL(url);
File sdCardDir = Environment.getExternalStorageDirectory();
File imgFile = new File(sdCardDir, "image");
if( !imgFile.exists() ){
imgFile.mkdir();
}
File img = new File(imgFile, "xxx");
FileOutputStream fos = null;
try {
fos = new FileOutputStream(img);
byte[] bytes = new byte[1024];
int len = 0;
while( (len = is.read(bytes))!=-1 ){
fos.write(bytes, 0, len);
}
fos.flush();
fos.close();
is.close();
} catch (FileNotFoundException e) {
Log.i(TAG, e.toString());
} catch (IOException e) {
Log.i(TAG, e.toString());
e.printStackTrace();
}
handler.sendEmptyMessage(IMAGE_SUCCESS);
} else {
Log.i(TAG, "sd not-existence");
handler.sendEmptyMessage(IMAGE_FAILURE);
}
};
}.start();
break;
default:
break;
}
}
public MyHandler handler = new MyHandler(this);
private static class MyHandler extends Handler {
WeakReference<MainActivity> mActivity;
MyHandler(MainActivity mActivity){
this.mActivity = new WeakReference<MainActivity>(mActivity);
}
@Override
public void handleMessage(Message msg) {
switch(msg.what){
case IMAGE_FAILURE:
Toast.makeText(mActivity.get()
, "Image Failure", Toast.LENGTH_LONG).show();
break;
case IMAGE_SUCCESS:
Log.i(TAG, "success");
FileInputStream fis = null;
byte[] bytes = new byte[1024];
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int len;
try {
File sdCardDir = Environment.getExternalStorageDirectory();
File imgFile = new File(sdCardDir, "image/xxx");
fis = new FileInputStream(imgFile);
while( (len=fis.read(bytes))!=-1 ){
baos.write(bytes, 0, len);
}
} catch (FileNotFoundException e) {
Log.i(TAG, e.toString());
} catch (IOException e) {
Log.i(TAG, e.toString());
}
Bitmap bMap = BitmapFactory.decodeByteArray(
baos.toByteArray(), 0, baos.toByteArray().length);
mActivity.get().iv.setImageBitmap(bMap);
try {
baos.flush();
baos.close();
} catch (IOException e) {
Log.i(TAG, e.toString());
}
}
}
}
}
主要是处理handler的静态内部类MyHandler的弱引用,不会阻碍Activity回收,弱引用就是不会影响计数器状态的引用。这意味着即使我们拥有对某个对象的弱引用也不会阻止它被清除