从片段处理相机应用程序的正确方法,而不会崩溃

时间:2015-07-13 11:34:15

标签: android android-fragments android-camera-intent onactivityresult

这是一个重复出现的问题,我过去没有找到一个好的解决方案。 我的应用程序基于具有多个子片段的单个活动。

我想做什么:

在我的一些片段中,我想用手机自带的相机应用拍照,并且都为用户显示图像,然后将其上传到我的服务器。

我现在做什么

现在,我用我的相机意图调用StartActivityForResult,这很好。然后我从onActivityResult收到我需要的内容,并能够在图像视图中显示拍摄的图像,并将其发送到我的服务器。

问题

有时我的onActivityResult被调用。我的片段一直没有启动或只是通过操作系统从内存中刷新(据我了解)。 这意味着变量现在具有null-references。 我从类似问题中读到的是OnCreateView()应该在OnActivityResult()之前被调用。

所以我在这里要做的是将片段状态保存到我的ArgumentsonDestroyView()中的onSaveInstanceState(),然后尝试恢复诸如临时{{1}之类的变量}}。然而,这里的片段似乎用一个新的Bundle启动Fragment而不是我为它创建的那个,并且由于我的相机文件为空而导致我的应用程序崩溃。

这也很难测试,因为这只是偶尔发生一次。

代码

Camera Image FilePath来自saveState()onDestroyView()

onSaveInstanceState()

@Override protected Bundle saveState() { Bundle state = new Bundle(); state.putSerializable("tempCameraFile", tempCameraFile); return state; } 最后由restoreStates()

调用
onCreateView()

我真的希望在使用碎片时我有一个明显的错误,而且有人可以帮助我。

这是一个反复出现的问题,我已经解决了从我的Activity中破坏和重新创建片段的非常难看的实现,但我现在想以正确的方式执行此操作。

3 个答案:

答案 0 :(得分:1)

问题是你根本没有保存你的状态。

@Override
public void onSaveInstanceState(Bundle outState){
    super.onSaveInstanceState(outState);
    saveStateToArguments();
}

outState包含将保存的所有值,但包含您的方法  saveStateToArguments();将值保存在另一个包中。 outState和您的捆绑包不相关,因此不会保存任何内容。 此外,无需拨打saveStateToArguments();中的onDestroyView,因为onSaveInstanceState会被调用。

只需将代码更改为以下内容:

@Override
public void onSaveInstanceState(Bundle outState){
    super.onSaveInstanceState(outState);
    outState.putSerializable("tempCameraFile", tempCameraFile);
}

并在方法onRestoreInstanceState

中恢复状态
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
 super.onRestoreInstanceState(savedInstanceState);
 if (savedInstanceState != null) {
   tempCameraFile = (File) savedInstanceState.getSerializable("tempCameraFile");
 }
}

因为生命周期如下:

  • 的onCreate
  • 在onStart
  • onRestoreInstanceState
  • onActivityResult
  • 的onResume

请参阅State of Activity while in onActivityResult question

答案 1 :(得分:0)

使用activity启动相机应用程序并使用activity的onActivityResult来确定片段是否存在。如果它没有重新初始化片段。

getActivity().startActivityForResult(intent);

答案 2 :(得分:0)

问题是系统在低内存中杀死后台活动。

解决方案

  • 保存ActivityFragment

    的状态
    /**
     * Handled take camera photo on low memory maybe activity on background killed, need to save state.
     */
    private Uri cameraMediaOutputUri;
    @Override
    public Uri getCameraMediaOutputUri() {
        return cameraMediaOutputUri;
    }
    
    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        outState.putParcelable("cameraMediaOutputUri", cameraMediaOutputUri);
        super.onSaveInstanceState(outState);
    }
    
  • 恢复状态,此处为技巧,因为Activity上的恢复状态与Fragment不同。

恢复活动状态

@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    if (savedInstanceState !=null && savedInstanceState.containsKey("cameraMediaOutputUri"))
        cameraMediaOutputUri = savedInstanceState.getParcelable("cameraMediaOutputUri");
}

恢复片段状态 Fragment Life Cycle

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    if (savedInstanceState !=null && savedInstanceState.containsKey("cameraMediaOutputUri"))
        cameraMediaOutputUri = savedInstanceState.getParcelable("cameraMediaOutputUri");
}