防止handler占用Activity,导致Activity无法按时回收

简述:

这种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回收,弱引用就是不会影响计数器状态的引用。这意味着即使我们拥有对某个对象的弱引用也不会阻止它被清除

你可能感兴趣的:(防止handler占用Activity,导致Activity无法按时回收)