android进阶3step1:Android组件通信——横竖屏切换状态保持

 

横竖屏切换状态保持

掌握手机横竖屏切换时Activity的各种变化,以及掌握如何保护横竖屏切换前的数据和恢复现场

学习内容

  • Activity的状态
  • ? 运行时系统配置变更
  • ? 应对配置变更
  • ? 保存和恢复Activity的状态
  • ? Fragment状态

带着问题学习! 

  •  Activity的哪些状态需要被保存和恢复?
  • ? 发生运行时系统配置变更时系统会做什么?? 如何应对系统配置变更?
  • ? 如何保存和恢复Activity的状态?
  • ? 如何保持Fragment的状态?

 一、运行时系统配置变更

有以下三种情况使系统配置变更

  1. ? 屏幕方向从竖屏变为横屏? 
  2. 键盘可见性从可见到不可见? 
  3. 系统语言从英文切换到中文

 

二、现场保护Activity方式1(屏幕变换)

屏幕变化时系统会做什么?? 

  1. 销毁正在运行的Activity对象
  2. 创建一个新的Activity对象

一、应对配置变更-限定方向

在AndroidManifest.xml中的Activity标签中写

android:screenOrientation="portrait" 限定activity只支持竖屏,不支持横屏。

<!--android:screenOrientation="portrait" 限定activity只支持竖屏-->
<activity
    android:name=".Main2Activity"
    android:screenOrientation="portrait"></activity>

 二、应用配置变更-自己处理

在AndroidManifest.xml中的Activity标签中写

 android:configChanges="orientation|screenSize|keyboardHidden" 

自己处理屏幕发生改变后的方向,屏幕位置,键盘的可见性,实现自己处理横竖屏变化,无需系统重启Activity。

        <!-- android:configChanges="orientation|screenSize|keyboardHidden" 自己处理屏幕翻转时自己处理-->
        <activity
            android:name=".Main2Activity"
            android:configChanges="orientation|screenSize|keyboardHidden"></activity>

三、应用配置变更-让系统处理配置变更

取消在AndroidManifest.xml中上述的操作,让系统自己配置

例如,我们想要实现竖屏显示布局1,横屏显示布局2,那么就要通过以下重写的方法了的bundle来保存状态

 

  • ?onSaveInstanceState? 
  • onCreate
  • ? onRestoreInstanceState

 

分析保存时机:

onSaveInstanceState的执行

  1. ? 按HOME键时? 
  2. 被来电覆盖时
  3. 屏幕旋转
  4. 用户按返回键时 

 四、保存与恢复状态

系统配置发生改变后,视图是系统默认保存的,但是不会保存成员状态,但是要注意以下几点: 

  1. ? 组件必须设置了id属性
  2.  实现了onSaveInstanceState回调 (利用Bundle实现保存)在状态改变时执行,将这个bundle传给onRestoreInstanceState
  3. ? 实现了onRestoreInstanceState回调(利用Bundle实现恢复)在新建或者重启Activity后会执行
  • 可以选择再onRestoreInstanceState进行恢复状态,也可以在onCreate中进行恢复,注意判空

 对象不会保存,所以自己重写以上两种方法来put、get。

  private static final String TAG = "Main2Activity";

    /**
     * 可以在oncreate恢复
     *
     * @param savedInstanceState
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        if (savedInstanceState != null) {
            Log.e(TAG, "onCreate: " + Integer.toHexString(savedInstanceState.hashCode()));
            Log.e(TAG, "onCreate中拿值:" + savedInstanceState.get("key"));
        }
    }

    /**
     * 也可以在onRestoreInstanceState中恢复
     */
    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        Log.e(TAG, "onRestoreInstanceState: " +Integer.toHexString(savedInstanceState.hashCode()));
        Log.e(TAG, "onRestoreInstanceState中拿值: " + savedInstanceState.get("key"));
    }

    /**
     * 实现系统配置更改后状态的保存
     *
     * @param outState
     */
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString("key", "value");
        Log.e(TAG, "onSaveInstanceState: " + Integer.toHexString(outState.hashCode()) + " ");
    }

结果: 

E/Main2Activity: onSaveInstanceState: dcb5ea6 
E/Main2Activity: onCreate: dcb5ea6 
onCreate中拿值:value
E/Main2Activity: onRestoreInstanceState: dcb5ea6
onRestoreInstanceState中拿值: value

五、现场保护Fragment

 

一、保持Fragment对象

  • ? 扩展Fragment(自定义Fragment)
  • ? 在onCreate函数里调用setRetainInstance(true);
  • ? 把Fragment对象添加到Activity中
  • ? 当Activity重启时,通过FragmentManager获取此Fragment对象

这是一个点击Fragment里面button进行累加,然后旋转屏幕看是否 能保存fragment的状态 

MyFragment.java中 


import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;


public class MyFragment extends Fragment {

    private static final String TAG = "BlankFragment-vv";
    private int countNum;


    public MyFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate: ");
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_blank, container, false);
        final TextView tv_count = view.findViewById(R.id.tv_count);
        tv_count.setText(String.valueOf(countNum));
        final Button bt_add = view.findViewById(R.id.bt_start);
        bt_add.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                tv_count.setText(String.valueOf(++countNum));
            }
        });


        return view;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }
}

MainActivty中将上面的Fragment添加进来


import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity-vv";
    private Fragment fragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //不需要布局文件
        //1。新建fragment对象
        fragment = new MyFragment();
        FragmentManager fm = getSupportFragmentManager();
        //添加到这个activity中
        fm.beginTransaction()
                .replace(android.R.id.content, fragment, "MyFragment")
                .commit();
        Log.d(TAG, "onCreate: ");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy: ");
    }
}

 当进行屏幕翻转的时候

11-25 11:15:56.715 6011-6011/com.demo.fragmentdemo2 D/MainActivity-vv: onCreate: 
11-25 11:15:56.745 6011-6011/com.demo.fragmentdemo2 D/MyFragment-vv: onCreate: 
11-25 11:16:03.863 6011-6011/com.demo.fragmentdemo2 D/MyFragment-vv: onDestroy: 
11-25 11:16:03.863 6011-6011/com.demo.fragmentdemo2 D/MainActivity-vv: onDestroy: 
11-25 11:16:03.892 6011-6011/com.demo.fragmentdemo2 D/MyFragment-vv: onCreate: 
11-25 11:16:03.892 6011-6011/com.demo.fragmentdemo2 D/MainActivity-vv: onCreate: 
11-25 11:16:03.944 6011-6011/com.demo.fragmentdemo2 D/MyFragment-vv: onCreate: 
11-25 11:16:03.945 6011-6011/com.demo.fragmentdemo2 D/MyFragment-vv: onDestroy: 

Fragment和Activity被销毁又重新创建了,上面已经讲过如何保存Activity的状态了,那么Fragment的状态怎么保存呢?

1.在MyFragment 的onCreate中调用        setRetainInstance(true);

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //告诉系统我要保存fragment对象
        setRetainInstance(true);
        Log.d(TAG, "onCreate: ");
    }

2.在MainActivity中的Oncreate方法中

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //不需要布局文件
        FragmentManager fm = getSupportFragmentManager();
        //通过第一次加载fragment设置的tag找到fragment
        fragment = fm.findFragmentByTag("MyFragment");
        if (fragment == null) {
            //1.如果找不到才新建
            fragment = new MyFragment();
            //添加到这个activity中
            fm.beginTransaction()
                    .replace(android.R.id.content, fragment, "MyFragment")
                    .commit();
        }
        Log.d(TAG, "onCreate: ");
    }

结果:Fragment没有被销毁和新建

11-25 11:21:23.959 6554-6554/? D/MainActivity-vv: onCreate: 
11-25 11:21:23.991 6554-6554/? D/MyFragment-vv: onCreate: 
11-25 11:21:38.448 6554-6554/com.demo.fragmentdemo2 D/MainActivity-vv: onDestroy: 
11-25 11:21:38.514 6554-6554/com.demo.fragmentdemo2 D/MainActivity-vv: onCreate: 

 二、保存和恢复Fragment的状态

Activity好Fragment有何共同点和不同点在保存状态的时候:

相同点:和activity一样可以在? onSaveInstanceState?中保存fragment的状态

不同点:fragment 在onActivityCreated或oncreate方法中恢复状态没onRestoreInstanceState的方法,而Acitivity中有

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值