【问题标题】:Slow performance when using a Camera Preview in a fragment在片段中使用相机预览时性能下降
【发布时间】:2015-03-19 23:03:13
【问题描述】:

我的应用包含三个片段。我需要保持用户体验流畅,所以我使用 setOffscreenPageLimit() 方法让它们在内存中保持活跃。

问题:当我开始一个新活动(甚至是空的)时,它加载缓慢。完成后也一样。

我知道这是来自我的相机预览片段,因为当我注释掉相机的初始化时,一切都运行得非常顺利。

这是我在 OnResume 方法上初始化相机预览的方式:

mCamera = GetCameraInstance(currentCameraId);

//-- Set the SurfaceView
preview = (SurfaceView) view.findViewById(R.id.camera_preview);
mSurfaceHolder = preview.getHolder();
mSurfaceHolder.addCallback(this);

if (mCamera != null) {

  mCamera.setPreviewDisplay(mSurfaceHolder);
  mCamera.startPreview();

}

当新活动启动时,会调用surfaceDestroyed 方法来销毁Camera 预览。当新 Activity 终止时,应用会再次重新创建相机视图。

@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
    if (mCamera != null) {
        mCamera.stopPreview();
        mCamera.release();
        mCamera = null;
    }
}

在 traceview 上看到的 stopPreview() 和 release() 方法所花费的时间。销毁相机预览大约需要 700 毫秒。

Screenshot of Traceview

【问题讨论】:

  • 使用 Traceview 确定您的时间都花在了哪里。
  • 大约 700ms 用于销毁和释放相机。重新创建相机预览需要 280 毫秒。 PS:我没有足够的代表来发布截图......
  • “我没有足够的代表来发布截图”——欢迎您将图片上传到其他地方并在此处链接到它们。 “大约 700 毫秒用于销毁和释放相机”——我没有尝试将 stopPreview()release() 移动到后台线程中,但在你的情况下这值得做一个实验。
  • stopPreview()release() 放入后台线程可以解决这个问题。谢谢
  • 啊,很好。我担心一个或两个会与主应用程序线程绑定在一起,以至于在后台线程中调用它们会导致某种错误。

标签: android android-fragments camera


【解决方案1】:

根据@CommonsWare 的建议,我是这样做的。

首先,我将 mCamera 变量放在 Application 类中

public Camera mCamera;

然后,我将 AsyncTask 放在我的片段中

 private class ControlCameraTask extends AsyncTask<Integer, Void, Void> {

    protected Void doInBackground(Integer... urls) {

        //--
        if (app.mCamera != null) {
            app.mCamera.stopPreview();
            app.mCamera.release();
            app.mCamera = null;
        } else {
            app.mCamera = GetCameraInstance(currentCameraId);                
            app.mCamera.setPreviewDisplay(app.mSurfaceHolder);
            app.mCamera.startPreview();
        }

        return null;
    }
 }

最后,我只是在onResumeonPausemethods 上调用我的AsyncTask

@Override
public void onResume() {
    super.onResume();
    new ControlCameraTask().execute(1);
}

@Override
public void onPause() {
    super.onPause();
    new ControlCameraTask().execute(1);
}

PS:为了便于阅读,我删除了 trycatches。

【讨论】:

    猜你喜欢
    • 2014-10-25
    • 2019-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-21
    • 1970-01-01
    相关资源
    最近更新 更多