垃圾收集原因:MediaPlayer 未发布就完成了 [英] Garbage Collection causes : MediaPlayer finalized without being released

查看:40
本文介绍了垃圾收集原因:MediaPlayer 未发布就完成了的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

经过大量调试,我终于找到了导致此错误的原因!垃圾收集!

After a lot of debugging I finally found what is causing this error! Garbage Collection!

我在媒体视图中播放了一个视频,我正在后台寻找来自 Rest API 的新视频.

I have a video playing in media view and in the background I am looking for new videos from a Rest API.

我时不时地看到垃圾收集在运行:

Every now and then I see the Garbage collection running:

02-22 13:14:57.969: D/dalvikvm(16888): GC_EXPLICIT freed 152K, 4% free 6746K/6979K, paused 2ms+2ms

紧随其后的是:

02-22 13:14:57.969: W/MediaPlayer-JNI(16888): MediaPlayer finalized without being released

所以我每 5 秒调用一次 System.gc() 对其进行测试.

So I tested it by calling System.gc() every 5 seconds.

一旦第一次 GC 被调用,它就会发生!

As soon as the first GC is called it happens!

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

为什么会这样?我可以预防吗?

Why does this happen? Can I prevent it?

播放视频:

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();
        }
    }

当它完成时:

@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();
        }


    }

推荐答案

我认为这是因为您在方法范围内创建媒体播放器,因此,当方法完成时,它超出了范围.这意味着没有引用,因此可以进行垃圾收集.

I think this is because you create the media player within the scope of the method, therefore, when the method completes, it goes out of scope. This means there are no references, so is ok for garbage collection.

这意味着,它甚至可以在调用 onCompletion 之前被 GC 释放,因此在清除之前不会释放.相反,您需要将媒体播放器的引用作为成员变量存储在您的类中.

This means, it can be free'd by the GC before it has even called onCompletion, hence won't release before cleared. Instead, you need to store a reference to the media player as a member variable in your class.

这篇关于垃圾收集原因:MediaPlayer 未发布就完成了的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆