Har*_*rry 30 android garbage-collection android-asynctask
经过大量的调试后我终于找到了导致此错误的原因!垃圾收集!
我在媒体视图中播放视频,在后台我正在寻找来自Rest API的新视频.
我偶尔会看到垃圾收集运行:
02-22 13:14:57.969: D/dalvikvm(16888): GC_EXPLICIT freed 152K, 4% free 6746K/6979K, paused 2ms+2ms
Run Code Online (Sandbox Code Playgroud)
直到那之后:
02-22 13:14:57.969: W/MediaPlayer-JNI(16888): MediaPlayer finalized without being released
Run Code Online (Sandbox Code Playgroud)
所以我每隔5秒就调用一次System.gc()来测试它.
一旦第一个GC被调用就会发生!
02-22 13:19:47.813: D/dalvikvm(17060): GC_EXPLICIT freed 167K, 5% free 6745K/7047K, paused 2ms+2ms ---- I call GC
02-22 13:19:47.813: W/MediaPlayer-JNI(17060): MediaPlayer finalized without being released ---- VIDEO PLAY INTERRUPTED
Run Code Online (Sandbox Code Playgroud)
为什么会这样?我能预防吗?
播放视频:
private void playMedia(int playListIndex) throws IOException {
File mediadir = getDir("tvr", Context.MODE_PRIVATE);
filelist = mediadir.listFiles();
Log.i("media player", "play media!");
String path = filelist[playListIndex].getAbsolutePath();
FileInputStream fileInputStream = new FileInputStream(path);
final Uri uri = Uri.parse(path);
String filename = filelist[playListIndex].getName();
if (filename.contains("image")) {
imageView = (ImageView)findViewById(R.id.imageView);
imageView.setVisibility(View.VISIBLE);
imageView.setImageURI(uri);
mHandler.postDelayed(new Runnable() {
public void run() {
imageView.setVisibility(View.GONE);
imageView.setImageURI(uri);
onCompletion(null);
}
}, 4000);
} else if (filename.contains("video")) {
MediaPlayer pl = new MediaPlayer();
pl.setOnCompletionListener(this);
pl.setDisplay(holder);
pl.setDataSource(fileInputStream.getFD());
pl.prepare();
pl.start();
}
}
Run Code Online (Sandbox Code Playgroud)
完成后:
@Override
public void onCompletion(MediaPlayer mp) {
Log.i("media player", "play next please!");
if (mp != null) {
mp.release();
}
// play next video
currentMedia++;
if (currentMedia > playList.size() - 1) {
currentMedia = 0;
}
try {
playMedia(currentMedia);
} catch (IOException e) {
e.printStackTrace();
}
}
Run Code Online (Sandbox Code Playgroud)
T. *_*ley 70
我认为这是因为您在方法范围内创建了媒体播放器,因此,当方法完成时,它超出了范围.这意味着没有引用,因此可以进行垃圾回收.
这意味着,它可以在GC调用onCompletion之前被释放,因此在清除之前不会释放.相反,您需要将对媒体播放器的引用存储为类中的成员变量.
Jas*_*key 11
Java GC仅管理内存.因此,当使用其他资源(例如文件,套接字等)时,您需要手动管理它们.对于MediaPlayer,文档提到:
还建议一旦不再使用MediaPlayer对象,立即调用release(),以便可以立即释放与MediaPlayer对象关联的内部播放器引擎使用的资源.资源可能包括单一资源(如硬件加速组件)和调用release()失败可能导致MediaPlayer对象的后续实例回退到软件实现或完全失败.
因此,当您完成MediaPlayer实例时,您需要确保在该实例上显式调用release().执行此操作的好地方可能是包含Activity的生命周期方法,例如onDestroy().否则,当最终垃圾收集该MediaPlayer实例时(在您不再引用它之后的某个任意时间),终结器将注意到您从未调用release()并将输出您看到的警告.
| 归档时间: |
|
| 查看次数: |
18356 次 |
| 最近记录: |