由于某个对象持有了其他对象的引用导致 ,导致无法 GC。
1:合理的使用context–比如我们常使用的Toast,Service,最好使用getApplicationContext(),因为这些在activity结束的时候可能仍在运行
下图通过图片说明国关于context的使用)
2:不要在activity中使用AsyncTask的强引用,如下是不行的:
class MyActivity extends Activity {
private AsyncTaskmyTask = new AsyncTask() {
//内部类隐含了对activity的一个强引用,强引用是无法被gc回收的;
}
}
我们异步获取手机音频文件 做个小范例:
private static class ScanRingsPhoneMusic extends AsyncTask{
private WeakReferenceactivityReference;
// only retain a weak reference to the activity
ScanRingsPhoneMusic(MusicListActivity context) {
activityReference = new WeakReference<>(context);
}
@Override
protected Void doInBackground(Void... voids) {
MusicListActivity activity = activityReference.get();
getAllSongs(activity);
return null;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
PublicUtils.getInstance().mediaPlayerRelease();
mHandler.removeCallbacksAndMessages(null);
}
public static void getAllSongs(MusicListActivity activity) {
Cursor cursor = activity.getApplicationContext().getContentResolver().query(
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
new String[] { MediaStore.Audio.Media._ID,
MediaStore.Audio.Media.DISPLAY_NAME,
MediaStore.Audio.Media.TITLE,
MediaStore.Audio.Media.DURATION,
MediaStore.Audio.Media.ARTIST,
MediaStore.Audio.Media.ALBUM,
MediaStore.Audio.Media.YEAR,
MediaStore.Audio.Media.MIME_TYPE,
MediaStore.Audio.Media.SIZE,
MediaStore.Audio.Media.DATA },
MediaStore.Audio.Media.MIME_TYPE + "=? or "
+ MediaStore.Audio.Media.MIME_TYPE + "=?",
new String[] { "audio/mpeg", "audio/x-ms-wma" }, null);
if (cursor.moveToFirst()) {
BackGroundMusic backGroundMusic = null;
while (cursor.moveToNext()) {
backGroundMusic = new BackGroundMusic();
// 文件名
backGroundMusic.setFileName(cursor.getString(1));
// 歌曲名
backGroundMusic.setTitle(cursor.getString(2));
// 时长
backGroundMusic.setDuration(cursor.getInt(3));
// 歌手名
backGroundMusic.setSinger(cursor.getString(4));
// 专辑名
backGroundMusic.setAlbum(cursor.getString(5));
// 年代
if (cursor.getString(6) != null) {
backGroundMusic.setYear(cursor.getString(6));
} else {
backGroundMusic.setYear("未知");
}
// 歌曲格式
if ("audio/mpeg".equals(cursor.getString(7).trim())) {
backGroundMusic.setType("mp3");
} else if ("audio/x-ms-wma".equals(cursor.getString(7).trim())) {
backGroundMusic.setType("wma");
}
// 文件大小
if (cursor.getString(8) != null) {
float size = cursor.getInt(8) / 1024f / 1024f;
backGroundMusic.setSize((size + "").substring(0, 4) + "M");
} else {
backGroundMusic.setSize("未知");
}
// 文件路径
if (cursor.getString(9) != null) {
backGroundMusic.setFilePath(cursor.getString(9));
}
Message message = activity.mHandler.obtainMessage();
message.what = 1;
message.obj=backGroundMusic;
activity.mHandler.sendMessage(message);
Log.i(TAG, backGroundMusic.toString());
}
cursor.close();
}
return ;
}
最后 附加一个 防止handler 内存泄漏的code
/**
* weakReference 防止内存泄漏
*/
private static class MyHandler extends Handler {
private WeakReferenceweakReference;
MyHandler(MusicListActivity activity) {
weakReference = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Log.e(TAG, "handleMessage: ");
MusicListActivity activity = weakReference.get();
switch (msg.what) {
case 1:
if (activity != null) {
BackGroundMusic backGroundMusic= (BackGroundMusic) msg.obj;
activity.mBackGroundMusicList.add( backGroundMusic);
if(activity.mBackGroundMusicList.size()>0){
activity.musicAdapter.notifyDataSetChanged();
}
}
break;
case 2:
activity.musicAdapter.notifyDataSetChanged();
break;
}
}
}
关于Android的内存泄漏 小伙伴 学会了吗?