private static class MyHandler extends Handler {
private final WeakReference<ChannelPlayer> parentReference;
protected MyHandler(ChannelPlayer activity) {
parentReference = new WeakReference<>(activity);
}
@Override
public void handleMessage(Message msg) {
final ChannelPlayer parent = parentReference.get();
if (parent != null) {
runWithParent(parent, msg);
}
super.handleMessage(msg);
}
public void runWithParent(ChannelPlayer parent, Message msg){
switch (msg.what) {
case MEDIA_PLAYER_VIDEO_NETSPEED: {
parent.mMediaController.setDownloadRate(String.valueOf(msg.arg1) + "KB/s");
parent.mNetSpeed.setTextSize(30);
parent.mNetSpeed.setText(String.format(mNetSpeedText, String.valueOf(msg.arg1) + "KB/s"));
break;
}
case MEDIA_PLAYER_BUFFERING_UPDATE: {
break;
}
case MEDIA_PLAYER_COMPLETION: {
break;
}
case MEDIA_PLAYER_LONG_PREPERING: {
// 如果长时间没有完成prepering,也就是长时间没有加载进视频直接换台
// 播放错误了,自动换台
parent.sendChannelBroken();
parent.sendChannelSave(true);
parent.changeSource();
break;
}
case MEDIA_PLAYER_INFO: {
if (msg.arg1 == IMediaPlayer.MEDIA_INFO_NOT_SEEKABLE) {
parent.mCanSeek = false;
} else if (msg.arg1 == IMediaPlayer.MEDIA_INFO_BUFFERING_START) {
parent.mProgressBarPreparing.setVisibility(View.VISIBLE);
parent.mNetSpeed.setVisibility(View.VISIBLE);
/*
* if (parent.mMediaPlayer.isPlaying()) {
* parent.mMediaPlayer.pause(); }
*/
} else if (msg.arg1 == IMediaPlayer.MEDIA_INFO_BUFFERING_END) {
parent.mEventHandler.removeMessages(MEDIA_PLAYER_LONG_PREPERING);
parent.mProgressBarPreparing.setVisibility(View.GONE);
parent.mProgressBarPreparingText.setVisibility(View.GONE);
parent.mProgressBarPreparingEpgNextText.setVisibility(View.GONE);
parent.mProgressBarPreparingEpgCurrentText.setVisibility(View.GONE);
parent.mNetSpeed.setVisibility(View.GONE);
/*
* if (parent.mMediaPlayer.isPlaying()) {
* parent.mMediaPlayer.start(); }
*/
}
break;
}
case MEDIA_PLAYER_CHANGE_CHANNEL: {
parent.setProgressBarPreParingText();
parent.resetMediaPlayer();
break;
}
case MEDIA_PLAYER_SETED_DATASOURCE: {
parent.setDataSource(parent.mMediaPath);
parent.mChannelList.setSelection(parent.favListAdapter.getSelection());
break;
}
case MEDIA_PLAYER_NUM_UPDATE: {
// 更新数字建
int position = parent.favListAdapter.getPosition(parent.playerKeyNum);
if (position > -1) {
parent.changeChannel(parent.favListAdapter.getBean(position));
parent.setChannelListTitle();
} else {
parent.mPlayerKeyView.setText(R.string.player_worng_channel_number);
}
parent.playerKeyNum = -1;
parent.mEventHandler.sendEmptyMessageDelayed(MEDIA_PLAYER_NUMKEY_HIDDEN, 2000);
break;
}
case MEDIA_PLAYER_NUMKEY_HIDDEN: {
parent.hiddenPlayerKeyNum();
break;
}
case EPG_LIST_HIDDEN: {
parent.mChannelEpgList.setVisibility(View.GONE);
break;
}
case EPG_LIST_SHOWING: {
parent.mChannelEpgList.setVisibility(View.VISIBLE);
break;
}
default:
break;
}
}
}
在“onCreate”中,我初始化处理程序:
mEventHandler = new MyHandler(this);
并在 onDestroy
mEventHandler.removeCallbacksAndMessages(null);
mEventHandler = null;
但它仍然显示泄漏!为什么?
03-18 20:49:40.135 14372-15987/tv.zvdio D/LeakCanary: In tv.zvdio:WTV-B-20160320:116.
03-18 20:49:40.135 14372-15987/tv.zvdio D/LeakCanary: * tv.zvdio.ui.player.ChannelPlayer has leaked:
03-18 20:49:40.135 14372-15987/tv.zvdio D/LeakCanary: * GC ROOT android.os.HandlerThread.<Java Local>
03-18 20:49:40.135 14372-15987/tv.zvdio D/LeakCanary: * leaks tv.zvdio.ui.player.ChannelPlayer instance
03-18 20:49:40.135 14372-15987/tv.zvdio D/LeakCanary: * Retaining: 5.8 MB.
03-18 20:49:40.135 14372-15987/tv.zvdio D/LeakCanary: * Reference Key: 4c2be65c-0924-44f2-ac68-333ff539507a
03-18 20:49:40.135 14372-15987/tv.zvdio D/LeakCanary: * Device: Xiaomi Xiaomi MI 3C cancro
03-18 20:49:40.135 14372-15987/tv.zvdio D/LeakCanary: * Android Version: 6.0.1 API: 23 LeakCanary: 1.4-beta1 02804f3
03-18 20:49:40.135 14372-15987/tv.zvdio D/LeakCanary: * Durations: watch=5020ms, gc=174ms, heap dump=6094ms, analysis=31821ms
03-18 20:49:40.135 14372-15987/tv.zvdio D/LeakCanary: * Details:
03-18 20:49:40.135 14372-15987/tv.zvdio D/LeakCanary: * Instance of android.os.HandlerThread
03-18 20:49:40.135 14372-15987/tv.zvdio D/LeakCanary: | mLooper = android.os.Looper@851452256 (0x32c02160)
03-18 20:49:40.135 14372-15987/tv.zvdio D/LeakCanary: | mPriority = 0
03-18 20:49:40.135 14372-15987/tv.zvdio D/LeakCanary: | mTid = 14895
03-18 20:49:40.135 14372-15987/tv.zvdio D/LeakCanary: | contextClassLoader = dalvik.system.PathClassLoader@851452736 (0x32c02340)
03-18 20:49:40.135 14372-15987/tv.zvdio D/LeakCanary: | daemon = false
03-18 20:49:40.135 14372-15987/tv.zvdio D/LeakCanary: | group = java.lang.ThreadGroup@1896861424 (0x710fcef0)
03-18 20:49:40.136 14372-15987/tv.zvdio D/LeakCanary: | hasBeenStarted = true
03-18 20:49:40.136 14372-15987/tv.zvdio D/LeakCanary: | id = 37566
03-18 20:49:40.136 14372-15987/tv.zvdio D/LeakCanary: | inheritableValues = null
03-18 20:49:40.136 14372-15987/tv.zvdio D/LeakCanary: | interruptActions = java.util.ArrayList@853002752 (0x32d7ca00)
03-18 20:49:40.136 14372-15987/tv.zvdio D/LeakCanary: | localValues = java.lang.ThreadLocal$Values@853002784 (0x32d7ca20)
03-18 20:49:40.136 14372-15987/tv.zvdio D/LeakCanary: | lock = java.lang.Object@851448048 (0x32c010f0)
03-18 20:49:40.136 14372-15987/tv.zvdio D/LeakCanary: | name = java.lang.String@851614976 (0x32c29d00)
03-18 20:49:40.136 14372-15987/tv.zvdio D/LeakCanary: | nativePeer = -1412130816
03-18 20:49:40.136 14372-15987/tv.zvdio D/LeakCanary: | parkBlocker = null
03-18 20:49:40.136 14372-15987/tv.zvdio D/LeakCanary: | parkState = 1
03-18 20:49:40.136 14372-15987/tv.zvdio D/LeakCanary: | priority = 5
03-18 20:49:40.136 14372-15987/tv.zvdio D/LeakCanary: | stackSize = 0
03-18 20:49:40.136 14372-15987/tv.zvdio D/LeakCanary: | target = null
03-18 20:49:40.136 14372-15987/tv.zvdio D/LeakCanary: | uncaughtHandler = null
03-18 20:49:40.136 14372-15987/tv.zvdio D/LeakCanary: | shadow$_klass_ = android.os.HandlerThread
03-18 20:49:40.136 14372-15987/tv.zvdio D/LeakCanary: | shadow$_monitor_ = 1252025007
03-18 20:49:40.136 14372-15987/tv.zvdio D/LeakCanary: * Instance of tv.zvdio.ui.player.ChannelPlayer
这是非常可悲的。顺便说一句,我的应用程序有两个进程,一个是主要活动,另一个用于媒体播放器,所以当我完成视频活动时,它是显示泄漏。