Android关于处理运行时变化如横竖屏切换等问题


一些Android设备在运行时,它的configuration可能会变化(例如:横竖屏切换,键盘的显示或者隐藏,所用语言的变化),当这些类似的变化发生时,如果在不做任何代码处理的情况下,android会重启当前正在运行的Activity(先回调onDestroy()方法,再回调onCreate()方法)。也许你会问android为什么会这么做,其实这么做的本意也就是为了通过加载一些可供替代的资源,帮助APP适应新的configuration。

为了处理好重新启动的Activity的数据或者状态,你可以在Activity的生命周期回调方onSaveInstanceState()来保存当前的数据,然后在方法onCreate()或者onRestoreInstanceState()中取出数据以及恢复状态,该方法适合数据量小,比较简单的情况。

然而,如果你像上一段中介绍的方法保存大量的数据和状态的话,可能会造成内存消耗比较大或者用户体验差的情况(个人体验较深的是:如果播放器的横竖屏切换,像上一段所说的保存播放位置和状态的话,会有明显的卡顿),这种情况下,一般你有两个选择:

a.在activity的configuration变化时,依然让你的Activity重启,但是给你的restart的新Activity对象传递一个可以保存状态的对象;(个人理解就是,这个对象在该Restart过程中一直是保留着的)

b.自己处理configuration变化,阻止系统重启Activity,并且监听configuration(这样可以手动地刷新Activity)。


对于a种处理思路,有一种利用Fragment保存数据的方案:

1.继承Fragment,并且声明数据对象;

2.在该Fragment的onCreate()方法中调用setRetainInstance(boolean)

3.把该Fragment对象加入到Activity中;

4.当Activity重启时,用FragmentManager重新获取该Fragment对象

public class RetainedFragment extends Fragment {

    // 你想保存的数据对象
    private MyDataObject data;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //使改fragment不会销毁
        setRetainInstance(true);
    }

    public void setData(MyDataObject data) {
        this.data = data;
    }

    public MyDataObject getData() {
        return data;
    }
}
特别需要注意的是:在fragment中的需要保存的数据对象,不应该与context有关,例如:Adapter,View之类的,否则可能造成内存泄露

下面给出activity的示例代码:

public class MyActivity extends Activity {

    private RetainedFragment dataFragment;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // 在restart()的时候找到包含数据的fragment
        FragmentManager fm = getFragmentManager();
        dataFragment = (DataFragment) fm.findFragmentByTag(“data”);

        // 第一次创建fragment
        if (dataFragment == null) {
            dataFragment = new DataFragment();
            fm.beginTransaction().add(dataFragment, “data”).commit();
            //从网络加载数据并保存到fragment中
            dataFragment.setData(loadMyData());
        }

        // 可以通过dataFragment.getData()获取数据
        ...
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        // 保存数据到fragment中
        dataFragment.setData(collectMyLoadedData());
    }
}
对于b中思路的处理方案:

如果你的App不需要再一些特定的configuration变化时刷新资源或者你的App设计本来就是要避免Activity重启,你可以按照以下步骤:

1.在manifest文件中,不需要重启的Activity中加入

android:configChanges="orientation|keyboardHidden"
该代码说明,在横竖屏切换或者软键盘显示隐藏的时候不会重启该Activity.

2.监听状态改变:

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    //检查横竖屏变化
    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        Toast.makeText(this, "landscape", Toast.LENGTH_SHORT).show();
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT){
        Toast.makeText(this, "portrait", Toast.LENGTH_SHORT).show();
    }
}

好了,个人第一次翻译,希望大家指正交流,哈哈




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值