内存泄漏和优化

时间:2014-07-31 15:31:27

标签: java android memory-leaks bitmap

我目前正在开发一个Android应用程序而且由于“Out of Memory”这个问题很少,我无法结束它,我认为我的代码中有两个部分可能导致泄漏。

  • 首先:应用程序必须同时播放12个音调(10个不同的频率)。我在Stack Overflow上找到了一段代码,允许我同时播放频率列表:(我认为这是由AudioTrack引起的,但我不知道如何解决它)

    public static void runList(final List<Double> freq) {
    
    if(audioTrack!=null){
        audioTrack.release();
        audioTrack=null;
    }
    
    final List<AudioTrack> audioTrackList = new ArrayList();
    final AudioTrack audioTrack0;
    final AudioTrack audioTrack1;
    
    
        genTone(freq.get(0));                       
        audioTrack0 = new AudioTrack(AudioManager.STREAM_MUSIC,
                (int) sampleRate, AudioFormat.CHANNEL_OUT_DEFAULT,AudioFormat.ENCODING_PCM_16BIT,
                generatedSnd.length, AudioTrack.MODE_STREAM);
    
        audioTrack0.play();
        audioTrack0.write(generatedSnd, 0, generatedSnd.length);
    
        genTone(freq.get(1));                       
        audioTrack1 = new AudioTrack(AudioManager.STREAM_MUSIC,
                (int) sampleRate, AudioFormat.CHANNEL_OUT_DEFAULT,AudioFormat.ENCODING_PCM_16BIT,
                generatedSnd.length, AudioTrack.MODE_STREAM);
    
        audioTrack1.play();
        audioTrack1.write(generatedSnd, 0, generatedSnd.length);
    
        handler.postDelayed(new Runnable() {
    
            @Override
            public void run() {
                //compteur : not more than 2 AudioTrack
                audioTrack0.release();
                audioTrack1.release();
            }
    
        }, 1000);
      }
    

(有了这个,我只能同时播放2个音调)

  • 然后:在同一个活动中,应用程序必须在屏幕上显示10个图像视图,每个视图都以不同的方式移动。所有这些图像视图先前已从位图解码。我认为泄漏来自这里。我试图在使用它之后释放Bitmap,但无所事事,我只能在崩溃之前显示在屏幕上移动的3或4个图像(Out of Memory)。可能有一种更好,更轻松的方式来动画图像,例如,为图像设置动画并使其遵循三角形方式,我用这个:

    private void triangleAnim(final ImageView patternImage, final int bpm, final int i, final double frequency) {
    
    resetN();
    int randomLeft = (int)(Math.random() * (maxRandomLeft-minRandomLeft)) + minRandomLeft;
    int randomTop = (int)(Math.random() * (maxRandomTop-minRandomTop)) + minRandomTop;
    
    final Animation anim = new TranslateAnimation(randomLeft, randomLeft + 300,randomTop,randomTop + 300 ); 
    anim.setDuration(60000/bpm);
    final Animation anim2 = new TranslateAnimation(randomLeft +300, randomLeft-300, randomTop+300, randomTop+300 );
    anim2.setDuration(60000/bpm);
    final Animation anim3 = new TranslateAnimation(randomLeft-300, randomLeft, randomTop+300, randomTop );
    anim3.setDuration(60000/bpm);
    su = new SoundUtils();
    su.setDuration(60000/bpm);
    patternImage.startAnimation(anim);
    
    anim.setAnimationListener(new Animation.AnimationListener() {
        @Override
        public void onAnimationEnd(Animation animation) {
            patternImage.startAnimation(anim2);
            ;
        }
    
        @Override
        public void onAnimationRepeat(Animation animation) {
        }
    
        @Override
        public void onAnimationStart(Animation animation) {
            // TODO Auto-generated method stub
        }
    });
    
    anim2.setAnimationListener(new Animation.AnimationListener() {
        @Override
        public void onAnimationEnd(Animation animation) {
            patternImage.startAnimation(anim3);
            ;
            incrementN();
        }
    
        @Override
        public void onAnimationRepeat(Animation animation) {    
        }
    
        @Override
        public void onAnimationStart(Animation animation) {
            // TODO Auto-generated method stub      
        }
    });
    
    anim3.setAnimationListener(new Animation.AnimationListener() {
        @Override
        public void onAnimationEnd(Animation animation) {                           
            if(n <= i){
                patternImage.startAnimation(anim);
    
            }
        }
    
        @Override
        public void onAnimationRepeat(Animation animation) {
        }
    
        @Override
        public void onAnimationStart(Animation animation) {
            // TODO Auto-generated method stub
        }
    });  }
    
  • 最后,是否有任何软件或代码或其他任何可以帮助我找到我的应用程序泄漏内存的地方?如果需要,我可以从LogCat链接您的错误。

对不起我的英文,希望没有太多错误。

更新:

这是我的logcat:

07-31 17:54:03.931: E/AndroidRuntime(15181): java.lang.OutOfMemoryError
07-31 17:54:03.931: E/AndroidRuntime(15181):    at      android.graphics.Bitmap.nativeCreate(Native Method)
07-31 17:54:03.931: E/AndroidRuntime(15181):    at android.graphics.Bitmap.createBitmap(Bitmap.java:903)
07-31 17:54:03.931: E/AndroidRuntime(15181):    at android.graphics.Bitmap.createBitmap(Bitmap.java:880)
07-31 17:54:03.931: E/AndroidRuntime(15181):    at android.graphics.Bitmap.createBitmap(Bitmap.java:847)
07-31 17:54:03.931: E/AndroidRuntime(15181):    at org.opencv.android.CameraBridgeViewBase.AllocateCache(CameraBridgeViewBase.java:451)
07-31 17:54:03.931: E/AndroidRuntime(15181):    at org.opencv.android.JavaCameraView.initializeCamera(JavaCameraView.java:184)
07-31 17:54:03.931: E/AndroidRuntime(15181):    at org.opencv.android.JavaCameraView.connectCamera(JavaCameraView.java:239)
07-31 17:54:03.931: E/AndroidRuntime(15181):    at org.opencv.android.CameraBridgeViewBase.onEnterStartedState(CameraBridgeViewBase.java:355)
07-31 17:54:03.931: E/AndroidRuntime(15181):    at org.opencv.android.CameraBridgeViewBase.processEnterState(CameraBridgeViewBase.java:318)
07-31 17:54:03.931: E/AndroidRuntime(15181):    at org.opencv.android.CameraBridgeViewBase.checkCurrentState(CameraBridgeViewBase.java:311)
07-31 17:54:03.931: E/AndroidRuntime(15181):    at org.opencv.android.CameraBridgeViewBase.enableView(CameraBridgeViewBase.java:228)
07-31 17:54:03.931: E/AndroidRuntime(15181):    at ui.fragment.TakePictureFragment$1.onManagerConnected(TakePictureFragment.java:71)
07-31 17:54:03.931: E/AndroidRuntime(15181):    at org.opencv.android.AsyncServiceHelper$1.onServiceConnected(AsyncServiceHelper.java:318)
07-31 17:54:03.931: E/AndroidRuntime(15181):    at android.app.LoadedApk$ServiceDispatcher.doConnected(LoadedApk.java:1119)
07-31 17:54:03.931: E/AndroidRuntime(15181):    at android.app.LoadedApk$ServiceDispatcher$RunConnection.run(LoadedApk.java:1136)
07-31 17:54:03.931: E/AndroidRuntime(15181):    at android.os.Handler.handleCallback(Handler.java:733)
07-31 17:54:03.931: E/AndroidRuntime(15181):    at android.os.Handler.dispatchMessage(Handler.java:95)
07-31 17:54:03.931: E/AndroidRuntime(15181):    at android.os.Looper.loop(Looper.java:157)
07-31 17:54:03.931: E/AndroidRuntime(15181):    at android.app.ActivityThread.main(ActivityThread.java:5356)
07-31 17:54:03.931: E/AndroidRuntime(15181):    at java.lang.reflect.Method.invokeNative(Native Method)
07-31 17:54:03.931: E/AndroidRuntime(15181):    at java.lang.reflect.Method.invoke(Method.java:515)
07-31 17:54:03.931: E/AndroidRuntime(15181):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1265)
07-31 17:54:03.931: E/AndroidRuntime(15181):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1081)
07-31 17:54:03.931: E/AndroidRuntime(15181):    at dalvik.system.NativeStart.main(Native Method)

要解码位图,我使用它:

private Bitmap decodeFile(File f){
    try {
        //decode image size
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(new FileInputStream(f),null,o);              
        //Find the correct scale value. It should be the power of 2.
        final int REQUIRED_SIZE=70;
        int width_tmp=o.outWidth, height_tmp=o.outHeight;
        int scale=1;
        while(true){
            if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
                break;
            width_tmp/=2;
            height_tmp/=2;
            scale++;
        }

        //decode with inSampleSize
        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize=scale;
        return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
    } catch (FileNotFoundException e) {}
    return null;

}

1 个答案:

答案 0 :(得分:0)

只需快速思考一下:确保关闭您的InputStream,BitmapFactory.decodeStream();似乎没有在源代码中执行此操作