onSaveInstanceState与onRestoreInstanceState应用

       事例场景:   在公司开发的产品中 有开启相机的功能  开启系统相机后  把拍下的照片保存 并且预览 然后拿到这个照片地址 返回     发布前已经测试 这个模块没有问题 后来在一款三星的机型上面 测试出来启动相机 后 拍照点击保存 不会再出现 我自己实现的 预览的界面 后来分析 是个别机型 ROM 太少 把拍照调用系统相机后 系统相机在前台  后台进程在资源不足的情况下 被系统回收了 导致这个BUG的出现  先贴一下 我没有解决BUG之前的代码 和 布局文件 如下:


public class TakingPicturesActivity extends FragmentActivity implements View.OnClickListener {

    private static final int START_CAMERA = 0x1;

    private final static int REQUEST_CAMERA = 0x2;

    private static final String ACTION_CAMERA = "android.media.action.IMAGE_CAPTURE";

    private Button mButtonCancel;

    private Button mButtonSend;

    private Uri mSavedPicUri;

    private FragmentManager fm;
    private FragmentTransaction ft;

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case START_CAMERA:
//开启系统相机
                    startCamera();
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.rc_ac_camera);
        mButtonCancel = (Button) findViewById(R.id.rc_back);
        mButtonSend = (Button) findViewById(R.id.rc_send);
        Message msg = Message.obtain();
        msg.what = START_CAMERA;
        mHandler.sendMessage(msg);
        mButtonCancel.setOnClickListener(this);
        mButtonSend.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.rc_send) {
            if (mSavedPicUri != null) {
                Intent data = new Intent();
                data.setData(mSavedPicUri);
                setResult(RESULT_OK, data);
            }
            finish();
        } else if (v.getId() == R.id.rc_back) {
            finish();
        }
    }

//调用系统相机拍照并且保存
    private void startCamera() {
        Intent intent = new Intent(ACTION_CAMERA);
        File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
        String name = System.currentTimeMillis() + ".jpg";

        File file = new File(path, name);
        mSavedPicUri = Uri.fromFile(file);
        RLog.d(this, "startCamera", "output pic uri =" + mSavedPicUri);

        intent.putExtra(MediaStore.EXTRA_OUTPUT, mSavedPicUri);
        startActivityForResult(intent, REQUEST_CAMERA);
    }


    @Override
    public void onActivityResult(int requestCode, int resultCode, final Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        switch (requestCode) {
            case REQUEST_CAMERA:
//用户对拍照完以后执行的操作
                if (resultCode == RESULT_CANCELED) {//用户选择取消保存
                    finish();
                    Log.e("TakingPicturesActivity","RESULT_CANCELED");
                }
                if (mSavedPicUri != null && resultCode == Activity.RESULT_OK) {//用户选择发送
                    new Handler().postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            showImage(mSavedPicUri);
                            Log.e("TakingPicturesActivity","RESULT_OK");
                        }
                    }, 10);
                }
                break;
        }
    }


    private final void showImage(Uri uri) {
        if (uri != null) {
//拿到uri 用桢布局展示 图片
            fm = getSupportFragmentManager();
            ft = fm.beginTransaction();
//这里的 fragment 就是用来展示 bitmap的
            PictureFragment mPhotoFragment = new PictureFragment(this, uri);
            ft.replace(R.id.rc_frame, mPhotoFragment);
            ft.commit();
        }else{
            finish();
        }
    }

}

布局文件的代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <FrameLayout
        android:id="@id/rc_frame"
        android:layout_width="match_parent"
        android:layout_height="0dip"
        android:layout_weight="1"
        android:background="#000"
        android:orientation="vertical" >
    </FrameLayout>

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="48dp"
        android:layout_gravity="bottom"
        android:background="#c000">
        <Button
            android:id="@id/rc_back"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:layout_marginRight="8dp"
            android:background="@null"
            android:gravity="center"
            android:text="取消"
            android:textColor="#fff"
            android:textSize="14sp" />

        <Button
            android:id="@id/rc_send"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_centerVertical="true"
            android:layout_marginLeft="50dp"
            android:background="@null"
            android:gravity="center"
            android:text="发送"
            android:textColor="#fff"
            android:textSize="14sp"
            android:layout_gravity="right|center_vertical" />
    </FrameLayout>


</LinearLayout>

图片展示一下,有直观的感觉

onSaveInstanceState与onRestoreInstanceState应用_第1张图片

问题的原因已经分析清楚  但是怎么解决这个问题呢 ? XXX主程帮忙分析 让我用onSaveInstanceState与onRestoreInstanceState来解决这个问题 这两个生命周期的方法比较冷门 虽然知道 但是根本没有正真的在实际应用过 我随即去网上看了几篇相关的博文 但是感觉将概念性的居多 看了半天还是没有特别明白  这边感谢Jenny姐 帮我对 onSaveInstanceState与onRestoreInstanceState的调试和分析 从中学到很多 下面说下具体解决步骤


@Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        mSavedPicUri =   Uri.parse(savedInstanceState.getString("photo_uri"));
        super.onRestoreInstanceState(savedInstanceState);
        //还原
        Log.e("TakingPicturesActivity","onRestoreInstanceState");
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        outState.putString("photo_uri",mSavedPicUri.toString());
        super.onSaveInstanceState(outState);
        //保存
        Log.e("TakingPicturesActivity","onSaveInstanceState");
    }

打断点log 崩溃 Carsh 发现是 mSavedPicUri 为null了 我们要保存系统 回收activity 的这个值  所以我们在 onCreate 里做 判断 

if(savedInstanceState == null) {
            Message msg = Message.obtain();
            msg.what = START_CAMERA;
            mHandler.sendMessage(msg);
        }

我们再来浏览整体的一个 代码 看看跟之前的不同之处 :

public class TakingPicturesActivity extends FragmentActivity implements View.OnClickListener {

    private static final int START_CAMERA = 0x1;

    private final static int REQUEST_CAMERA = 0x2;

    private static final String ACTION_CAMERA = "android.media.action.IMAGE_CAPTURE";

    private Button mButtonCancel;

    private Button mButtonSend;

    private Uri mSavedPicUri;

    private FragmentManager fm;
    private FragmentTransaction ft;

    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case START_CAMERA:
                    startCamera();
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.rc_ac_camera);
        mButtonCancel = (Button) findViewById(R.id.rc_back);
        mButtonSend = (Button) findViewById(R.id.rc_send);

        if(savedInstanceState == null) {
            Message msg = Message.obtain();
            msg.what = START_CAMERA;
            mHandler.sendMessage(msg);
        }

        mButtonCancel.setOnClickListener(this);
        mButtonSend.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.rc_send) {
            if (mSavedPicUri != null) {
                Intent data = new Intent();
                data.setData(mSavedPicUri);
                setResult(RESULT_OK, data);
            }
            finish();
        } else if (v.getId() == R.id.rc_back) {
            finish();
        }
    }

    private void startCamera() {
        Intent intent = new Intent(ACTION_CAMERA);
        File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
        String name = System.currentTimeMillis() + ".jpg";

        File file = new File(path, name);
        mSavedPicUri = Uri.fromFile(file);
        RLog.d(this, "startCamera", "output pic uri =" + mSavedPicUri);

        intent.putExtra(MediaStore.EXTRA_OUTPUT, mSavedPicUri);
        startActivityForResult(intent, REQUEST_CAMERA);
    }


    @Override
    public void onActivityResult(int requestCode, int resultCode, final Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        switch (requestCode) {
            case REQUEST_CAMERA:
                if (resultCode == RESULT_CANCELED) {
                    finish();
                    Log.e("TakingPicturesActivity","RESULT_CANCELED");
                }
                if (mSavedPicUri != null && resultCode == Activity.RESULT_OK) {
                    new Handler().postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            showImage(mSavedPicUri);
                            Log.e("TakingPicturesActivity","RESULT_OK");
                        }
                    }, 10);
                }
                break;
        }
    }


    private final void showImage(Uri uri) {
        if (uri != null) {
            fm = getSupportFragmentManager();
            ft = fm.beginTransaction();
            PictureFragment mPhotoFragment = new PictureFragment(this, uri);
            ft.replace(R.id.rc_frame, mPhotoFragment);
            ft.commit();
        }else{
            finish();
        }
    }


    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        mSavedPicUri =   Uri.parse(savedInstanceState.getString("photo_uri"));
        super.onRestoreInstanceState(savedInstanceState);
        //还原
        Log.e("TakingPicturesActivity","onRestoreInstanceState");
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        outState.putString("photo_uri",mSavedPicUri.toString());
        super.onSaveInstanceState(outState);
        //保存
        Log.e("TakingPicturesActivity","onSaveInstanceState");
    }
}
如此保存状态以后 在资源不足 被系统回收 顶层的任务栈退出后  恢复之前被回收的activity, 我们只需要保存 carsh 当时为null的值  

你可能感兴趣的:(android,技术)