android控件状态值保存的问题

之前在分析科室的疑难杂症中遇到一个问题,wifi的开关在横竖屏切换后,开关状态变化了,由开变为了关,如果是关的状态,切换后是关的状态(或者是由关变为了开,如果是开的状态,切换后是开的状态)。后来写了个demo,实现这种情况,demo所涉及到的原理是一样的,只是设置中代码盘综复杂,所以那个实际的wifi开关的问题,要复杂一些。

操作视频如下所示

横竖屏切换后开关状态变化

Mainactivity.java的布局文件

<com.fw.mytest.myLayout
    android:id="@+id/myLayout1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">
</com.fw.mytest.myLayout>

    <com.fw.mytest.myLayout
        android:id="@+id/myLayout2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
    </com.fw.mytest.myLayout>

myLayout是自定义控件,类如下,布局文件my_layout没什么特别的,就一个TextView,一个Switch

public class myLayout extends LinearLayout {

    public Switch mSwitch;

    public myLayout(Context paramContext, AttributeSet paramAttributeSet) {
        super(paramContext, paramAttributeSet);
        LayoutInflater.from(paramContext).inflate(R.layout.my_layout, (ViewGroup)this);
        mSwitch = findViewById(R.id.mySwitch);
        boolean isChecked = mSwitch.isChecked();
        Log.d("myLayout","mj_isChecked:"+isChecked+"mSwitch:"+mSwitch.hashCode());
    }


    @Override
      public Parcelable onSaveInstanceState() {
        Log.d("myLayout","mj_onSaveInstanceState_isChecked:"+mSwitch.isChecked());
        return super.onSaveInstanceState();
    }

    @Override
      public void onRestoreInstanceState(Parcelable state) {
        super.onRestoreInstanceState(state);
        Log.d("myLayout","mj_onRestoreInstanceState_isChecked:"+mSwitch.isChecked());
    }

}

Mainactivity的代码如下:

public class MainActivity extends AppCompatActivity {

    private myLayout myLayout1;
    private myLayout myLayout2;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        myLayout1 = (myLayout)findViewById(R.id.myLayout1);
        myLayout2 = (myLayout)findViewById(R.id.myLayout2);
    }


    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        boolean mSwitch1 = myLayout1.mSwitch.isChecked();
        boolean mSwitch2 = myLayout2.mSwitch.isChecked();
        Log.d("MainActivity","mj_onSaveInstanceState_mSwitch1:"+mSwitch1+",mSwitch2:"+mSwitch2);
    }

    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        boolean mSwitch1 = myLayout1.mSwitch.isChecked();
        boolean mSwitch2 = myLayout2.mSwitch.isChecked();
        Log.d("MainActivity","mj_onRestoreInstanceState_mSwitch1:"+mSwitch1+",mSwitch2:"+mSwitch2);
    }
}

横竖屏切换,主要log如下

01-18 11:13:15.159 24437 24437 D myLayout: mj_onSaveInstanceState_isChecked:false
01-18 11:13:15.159 24437 24437 D myLayout: mj_onSaveInstanceState_isChecked:true
01-18 11:13:15.159 24437 24437 D MainActivity: mj_onSaveInstanceState_mSwitch1:false,mSwitch2:true
01-18 11:13:15.327 24437 24437 D myLayout: mj_isChecked:falsemSwitch:232238890
01-18 11:13:15.333 24437 24437 D myLayout: mj_isChecked:falsemSwitch:222704312
01-18 11:13:15.339 24437 24437 D myLayout: mj_onRestoreInstanceState_isChecked:false
01-18 11:13:15.343 24437 24437 D myLayout: mj_onRestoreInstanceState_isChecked:false
01-18 11:13:15.343 24437 24437 D MainActivity: mj_onRestoreInstanceState_mSwitch1:true,mSwitch2:true

在MainActivity.java中onRestoreInstanceState方法中,恢复时,两个开关都变为了true。原因是因为他们ID是一样的,所以获取到的状态都是true。解决该问题,在onSaveInstanceState中主动保存下状态值。

控件Switch的状态值的onSaveInstanceState流程
Activity.java --onSaveInstanceState
PhoneWindow.java --saveHierarchyState
View.java --saveHierarchyState–dispatchSaveInstanceState

按ID值去保存的container.put(mID, state);

onRestoreInstanceState流程
Activity.java --onRestoreInstanceState
PhoneWindow.java --restoreHierarchyState
View.java --restoreHierarchyState–dispatchRestoreInstanceState

是按ID获取状态值的Parcelable state = container.get(mID);

在View.java中dispatchSaveInstanceState和dispatchRestoreInstanceState中添加log,以及MainActivity中添加打印switch的id的log

//dispatchSaveInstanceState,switch走了两次,值分别为false、true
01-01 20:53:30.449  4191  4191 D View    : mj_dispatchSaveInstanceState_mID:2131165252,state:CompoundButton.SavedState{cf53bde checked=false}
01-01 20:53:30.453  4191  4191 D View    : mj_dispatchSaveInstanceState_mID:2131165252,state:CompoundButton.SavedState{3c483d5 checked=true}

//dispatchRestoreInstanceState,switch走了两次,两次都是true
01-01 20:53:30.586  4191  4191 D myLayout: mj_onRestoreInstanceState_isChecked:false,mSwitchId:2131165252
01-01 20:53:30.590  4191  4191 D View    : mj_dispatchRestoreInstanceState_mID:2131165252,state:CompoundButton.SavedState{3c483d5 checked=true}
01-01 20:53:30.593  4191  4191 D myLayout: mj_onRestoreInstanceState_isChecked:false,mSwitchId:2131165252
01-01 20:53:30.594  4191  4191 D View    : mj_dispatchRestoreInstanceState_mID:2131165252,state:CompoundButton.SavedState{3c483d5 checked=true}

//可以看到两个switch的id是相同的
01-01 20:53:30.600  4191  4191 D MainActivity: mj_onRestoreInstanceState_mSwitch1:true,mSwitch2:true,mSwitch1Id:2131165252,mSwitch2Id:2131165252

另外,myLayout中的onRestoreInstanceState在view的dispatchRestoreInstanceState方法前执行的,所以打印的switch的状态是false

  • 11
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值