调用MediaScannerConnection 发生内存泄露的解决方法

调用MediaScannerConnection发起扫描时经常会发生内存泄露,例如:

 E ActivityThread: Activity FolderListActivity has leaked ServiceConnection android.media.MediaScannerConnection@ec2a697 that was originally bound here

从网上看到一种解决方法,就是把MediaScannerConnection单独放在一个类中,而不是直接在Activity中创建。

参考网址:

http://www.dreamincode.net/forums/topic/289977-service-connection-leak-error/

1.有问题的代码:

public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.createfile);
		setupVariables();
		checkState();
		
		//Locates the SD Card's path to create a new directory
		//If the directory does not exist, then it is created
		path = new File(Environment.getExternalStorageDirectory(), dirName);
		if(!path.exists()){
			path.mkdirs();
		}


		//if you can read and write to storage
		if (wEnable && rEnable) {
			// Can Read and Write
			confirm.setonclickListener(this);
			// creates the library file
			save.setonclickListener(this);
		}
	}

	private void setupVariables() {
	//The Variables are stored here

	}

	private void checkState() {
	//Checks the state of the external storage. Not relevant to the problem
	}

	public void onclick(View v) {
		switch (v.getId()) {
		case R.id.bConfirm:
			name = tv.getText().toString();
			
			if (name.equals("")) {
				error.setVisibility(View.VISIBLE);
			} 
			else {
				error.setVisibility(View.INVISIBLE);
				save.setVisibility(View.VISIBLE);
			}
			break;
			
		case R.id.bSave:
			name = tv.getText().toString() + ".txt";
			library = new File(path, name);
			
//This is where the problem occurs


			MediaScannerConnection.scanFile(FileCreation.this, new String[]{library.toString()}, 
				null, new MediaScannerConnection.OnScanCompletedListener() {
				      public void onScanCompleted(String path, Uri uri) {
						// TODO Auto-generated method stub
						runOnUiThread(new Runnable() {
							public void run() {
							   Toast.makeText(FileCreation.this,
								"Media scan completed",
								Toast.LENGTH_SHORT).show();
								}
							});
						}
					});
			finish();
			break;
		}

	}

2.建议的代码:

You are creating a media scanner and running it and then calling finish(); while the service is still connected! 
Create the following class :

import java.io.File;
import android.content.Context;
import android.media.MediaScannerConnection;
import android.media.MediaScannerConnection.MediaScannerConnectionClient;
import android.net.Uri;

public class SingleMediaScanner implements MediaScannerConnectionClient {

public interface ScanListener{
    public void onScanFinish();
}

private MediaScannerConnection mMs;
private File mFile;
private ScanListener listener;

public SingleMediaScanner(Context context, File f,ScanListener l) {
    listener = l;
    mFile = f;
    mMs = new MediaScannerConnection(context, this);
    mMs.connect();
}

@Override
public void onMediaScannerConnected() {
    mMs.scanFile(mFile.getAbsolutePath(), null);
}

@Override
public void onScanCompleted(String path, Uri uri) {
    mMs.disconnect();
    listener.onScanFinish();
}

}

Then in your code do the following:

new SingleMediaScanner(<context>,<File go here>,new ScanListener(){
public void onScanFinish()
{
finish();
Toast.makeText(FileCreation.this,"Media scan completed",Toast.LENGTH_SHORT).show();
});

3.修改后的代码:

package com.maclinCode;

import java.io.File;

import android.app.Activity;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.view.View;
import android.view.View.onclickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.maclinCode.SingleMediaScanner.ScanListener;

public class FileCreation extends Activity implements onclickListener {
	EditText tv;
	TextView error;
	Button save, confirm;
	boolean wEnable, rEnable;
	String name;
	
	File path = null;
	File fileName = null;
	File library = null;
	private String state;
	private static final String dirName = "GameLibrary";
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.createfile);
		setupVariables();
		checkState();
		
		//Locates the SD Card's path to create a new directory
		//If the directory does not exist, then it is created
		path = new File(Environment.getExternalStorageDirectory(), dirName);
		if(!path.exists()){
			path.mkdirs();
		}


		//if you can read and write to storage
		if (wEnable && rEnable) {
			// Can Read and Write
			confirm.setonclickListener(this);
			// creates the library file
			save.setonclickListener(this);
		}
	}

	private void setupVariables() {
		confirm = (Button) findViewById(R.id.bConfirm);
		save = (Button) findViewById(R.id.bSave);
		tv = (EditText) findViewById(R.id.FileName);

		error = (TextView) findViewById(R.id.tvError);
		state = Environment.getExternalStorageState();
		wEnable = rEnable = false;

	}

	private void checkState() {
		if (state.equals(Environment.MEDIA_MOUNTED)) {
			// Can Read and Write to storage
			wEnable = rEnable = true;
		}
		else{
			Toast.makeText(this, "Cannot use External Storage", Toast.LENGTH_SHORT).show();
			finish();
			return;
		}
	}

	public void onclick(View v) {
		switch (v.getId()) {
		case R.id.bConfirm:
			name = tv.getText().toString();
			
			if (name.equals("")) {
				error.setVisibility(View.VISIBLE);
			} 
			else {
				error.setVisibility(View.INVISIBLE);
				save.setVisibility(View.VISIBLE);
			}
			break;
			
		case R.id.bSave:
			name = tv.getText().toString() + ".txt";
			library = new File(path, name);
			
//			MediaScannerConnection.scanFile(FileCreation.this, new String[]{library.toString()}, 
//					null, new MediaScannerConnection.OnScanCompletedListener() {
//						public void onScanCompleted(String path, Uri uri) {
//							// TODO Auto-generated method stub
//							runOnUiThread(new Runnable() {
//								public void run() {
//									Toast.makeText(FileCreation.this,
//											"Media scan completed",
//											Toast.LENGTH_SHORT).show();
//								}
//							});
//						}
//					});
//			finish();
		new SingleMediaScanner(FileCreation.this, library, new ScanListener(){
				public void onScanFinish(){
					finish();
					Toast.makeText(FileCreation.this,
							"Media scan completed",
							Toast.LENGTH_SHORT).show();
				}
			});
			break;
		}

	}

}



posted on 2016-09-06 11:19  木鱼哥  阅读(514)  评论(0编辑  收藏  举报

导航