如何使用 OnsavedInstance 保存 Spinner 及其适配器并在之后恢复它?
How to save a Spinner and it's adapter using OnsavedInstance and restore it after?
我在处理应用程序中的两个旋转器 onSavedInstance
和 onRestoreInstance
时遇到问题。
我有两个 SpinnerAdapter
可以动态填充一对 ArrayAdapter<String>
- adapter1/adapter2 和 adapter3/adapter4。
在 onCreate 方法应用程序中为它们创建 4 个适配器,当用户按下 button1
它填充 spinnerFrom
和 spinnerTo
适配器 1 和适配器 2,当 button2
填充微调器时分别为适配器 3 和适配器 4。
据我了解生命周期 - 当屏幕旋转时,android 销毁应用程序,然后从头开始恢复它。
所以在 onSavedInstance
中,我将我的微调器放入包中
savedInstanceState.putInt("from",spinnerFrom.getSelectedItemPosition);
savedInstanceState.putInt("to",spinnertTo.getSelectedItemPosition());
恢复时我从包中检索它们:
spinnerFrom.setSelection(savedInstanceState.getInt("from"));
spinnertTo.setSelection(savedInstanceState.getInt("to"));
问题是:当应用程序恢复时它丢失了我的适配器并且它们得到了空值。
为了检查它,我创建了技术按钮和下一个代码:
protected void checkAdapter () {
//get Adapter from spinners
SpinnerAdapter valueAdapter = spinnerFrom.getAdapter();
SpinnerAdapter resultAdapter = spinnertTo.getAdapter();
if (valueAdapter == null | resultAdapter== null) {
Toast.makeText(this, “adapter null” , Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(this, “adapters not null” , Toast.LENGTH_SHORT).show();
}
}
问题:如何正确地将 AdroidSpinner 及其适配器放入 OnSavedInstance 包中,然后将其恢复到 onRestoreInstance 以防它不是在 onCreate 中而是在 onClick 方法中填充?
提前致谢!
应用java代码:
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.Spinner;
import android.widget.SpinnerAdapter;
import android.widget.TextView;
import android.widget.Toast;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class MainActivity extends AppCompatActivity {
protected double getEnteredValue;
protected SpinnerAdapter checkAdapter;
protected int pos;
protected ArrayAdapter<String> adapter 1, adapter2, adapter3,
adapter4;
//butterknife bindings
@BindView(R.id.unit_From_spinner)Spinner spinnerFrom;
@BindView(R.id.unit_To_spinner)Spinner spinnertTo;
@BindView(R.id.radio_result_group) RadioGroup resultGroup;
@BindView(R.id.radio_value_gropu) RadioGroup valueGroup;
@BindView(R.id.valueEditTextView) EditText valueEdit;
@BindView(R.id.resultView) TextView resultView;
@BindView(R.id.conver_button) Button convertButton;
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putString("result",resultView.getText().toString()); savedInstanceState.putString("value",valueEdit.getText().toString()); savedInstanceState.putInt("from",spinnerFrom.getSelectedItemPosition);
savedInstanceState.putInt("to",spinnertTo.getSelectedItemPosition());
savedInstanceState.putInt("radGroup1",resultGroup.getCheckedRadioButtonId());
savedInstanceState.putInt("radGroup2", valueGroup.getCheckedRadioButtonId());
super.onSaveInstanceState(savedInstanceState);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.unifiedlayout);
ButterKnife.bind(this);
//adapters for spinners
adapter1 = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_spinner_item,getResources().getStringArray( R.array.adapter_1) );
adapter2 = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_spinner_item,getResources().getStringArray(R.array. adapter_2));
adapter3 = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_spinner_item,getResources().getStringArray( R.array. adapter_3) );
adapter4 = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_spinner_item,getResources().getStringArray(R.array. adapter_4));}
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
resultView.setText(savedInstanceState.getString("result"));
valueEdit.setText(savedInstanceState.getString("value"));
spinnerFrom.setSelection(savedInstanceState.getInt("from"));
spinnertTo.setSelection(savedInstanceState.getInt("to"));
super.onSaveInstanceState(savedInstanceState);
}
//OnClick
@OnClick({R.id.button1, R.id.button2,R.id.button3,R.id.button4} )
public void setViewOnClickEvent(View view){
switch(view.getId()){
case R.id. button1:
fillSpinner(adapter1, adapter2); // fill spinner with values
break;
case R.id. button2:
fillSpinner(adapter3,
adapter4);
break;
//button for check if any adapter active
case R.id.buttonAdapter:
checkAdapter () ;
break;
}
}
//fill spinners when user checks radiobutton in radiogroups
protected void fillSpinner (final ArrayAdapter<String> spinnerToAdapter,
final ArrayAdapter<String> spinnerFromAdapter){
valueGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup valueGroup, int checkedId) {
pos = valueGroup.indexOfChild(findViewById(checkedId));
switch (pos) {
case 0:
spinnerFrom.setAdapter(spinnerToAdapter);
break;
case 1:
spinnerFrom.setAdapter(spinnerFromAdapter);
break;
}
}
});
resultGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup resultGroup, int checkedId) {
pos = resultGroup.indexOfChild(findViewById(checkedId));
switch (pos) {
case 0:
spinnertTo.setAdapter(spinnerToAdapter);
break;
case 1:
spinnertTo.setAdapter(spinnerFromAdapter);
break;
}
}
});
}
//simple method for check if both spinners has null value
protected void checkAdapter () {
//get Adapter from spinners
SpinnerAdapter valueAdapter = spinnerFrom.getAdapter();
SpinnerAdapter resultAdapter = spinnertTo.getAdapter();
if (valueAdapter == null | resultAdapter== null) {
Toast.makeText(this, “adapter null” , Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(this, “adapters not null” , Toast.LENGTH_SHORT).show();
}
}
编辑:答案并不完美,它还不能按我想要的方式工作,但这种方式让我有可能保存适配器:
1.Create 从适配器中检索要保存的字符串数组的方法:
public static String[] getStringArray(SpinnerAdapter adapter) {
String[] a = new String[adapter.getCount()];
for (int i = 0; i < a.length; i++)
a[i] = adapter.getItem(i).toString();
return a;
}
2.In onSavedInstanceState 放下一个代码:
// here i saving arraylist that ussualy i get from resources.
savedInstanceState.putStringArray(ADAPTER_TO,getStringArray(spinnerFrom.getAdapter()));
savedInstanceState.putStringArray(ADAPTER_FROM,getStringArray(spinnerFrom.getAdapter()));
3.In restoreInstance 创建新的适配器,它将用值填充您的微调器并使用 savedInstanceState.getStringArray(ADAPTER_TO) 填充保存的值:
toAdapter = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_spinner_item, savedInstanceState.getStringArray(ADAPTER_TO));
fromAdapter = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_spinner_item, savedInstanceState.getStringArray(ADAPTER_FROM));
//use spinner.setAdapter to set created adapter.
spinnerFrom.setAdapter (fromAdapter)
spinnerTo.setAdapter (toAdapter)
这仍然无法正常工作,但如果您想在旋转屏幕上保存微调器状态,您可以尝试使用此逻辑。
Spinner 有 onNothingSelected()
方法。
在那个方法中,尝试玩 spinneradapter.getLastVisiblePosition()
.
当您关闭应用程序时,保存最后的位置,当您回来时,使用最后的位置。
希望对你有帮助。
您可以使用两种方法实现此目的。 1)(推荐)使用 ViewModels(架构组件)2) 使用保存和恢复状态。
1).您可以创建一个 viewModel,只要用户选择某项,就调用具有指定值的 ViewModel。通过观察 ViewModel,您可以获得该值的最新更改(即使在旋转更改之后),因为 ViewModel 将保持活动状态。
3) 将用户的选择保存在 activity 内的局部变量中,然后在保存和恢复中,put
和 get
您的值如下所示:
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putInt("firstSpinnerPosition", variableThatHasTheChangedPosition);
savedInstanceState.putInt("secondSpinnerPosition", variableThatHasTheChangedPositionForSecond);
// other stuff.
}
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
variableThatHasTheChangedPosition = savedInstanceState.getInt("firstSpinnerPosition");
variableThatHasTheChangedPositionForSecond = savedInstanceState.getInt("secondSpinnerPosition");
//notify your adapter of the changes
}
我在处理应用程序中的两个旋转器 onSavedInstance
和 onRestoreInstance
时遇到问题。
我有两个 SpinnerAdapter
可以动态填充一对 ArrayAdapter<String>
- adapter1/adapter2 和 adapter3/adapter4。
在 onCreate 方法应用程序中为它们创建 4 个适配器,当用户按下 button1
它填充 spinnerFrom
和 spinnerTo
适配器 1 和适配器 2,当 button2
填充微调器时分别为适配器 3 和适配器 4。
据我了解生命周期 - 当屏幕旋转时,android 销毁应用程序,然后从头开始恢复它。
所以在 onSavedInstance
中,我将我的微调器放入包中
savedInstanceState.putInt("from",spinnerFrom.getSelectedItemPosition);
savedInstanceState.putInt("to",spinnertTo.getSelectedItemPosition());
恢复时我从包中检索它们:
spinnerFrom.setSelection(savedInstanceState.getInt("from"));
spinnertTo.setSelection(savedInstanceState.getInt("to"));
问题是:当应用程序恢复时它丢失了我的适配器并且它们得到了空值。
为了检查它,我创建了技术按钮和下一个代码:
protected void checkAdapter () {
//get Adapter from spinners
SpinnerAdapter valueAdapter = spinnerFrom.getAdapter();
SpinnerAdapter resultAdapter = spinnertTo.getAdapter();
if (valueAdapter == null | resultAdapter== null) {
Toast.makeText(this, “adapter null” , Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(this, “adapters not null” , Toast.LENGTH_SHORT).show();
}
}
问题:如何正确地将 AdroidSpinner 及其适配器放入 OnSavedInstance 包中,然后将其恢复到 onRestoreInstance 以防它不是在 onCreate 中而是在 onClick 方法中填充? 提前致谢!
应用java代码:
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.Spinner;
import android.widget.SpinnerAdapter;
import android.widget.TextView;
import android.widget.Toast;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class MainActivity extends AppCompatActivity {
protected double getEnteredValue;
protected SpinnerAdapter checkAdapter;
protected int pos;
protected ArrayAdapter<String> adapter 1, adapter2, adapter3,
adapter4;
//butterknife bindings
@BindView(R.id.unit_From_spinner)Spinner spinnerFrom;
@BindView(R.id.unit_To_spinner)Spinner spinnertTo;
@BindView(R.id.radio_result_group) RadioGroup resultGroup;
@BindView(R.id.radio_value_gropu) RadioGroup valueGroup;
@BindView(R.id.valueEditTextView) EditText valueEdit;
@BindView(R.id.resultView) TextView resultView;
@BindView(R.id.conver_button) Button convertButton;
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putString("result",resultView.getText().toString()); savedInstanceState.putString("value",valueEdit.getText().toString()); savedInstanceState.putInt("from",spinnerFrom.getSelectedItemPosition);
savedInstanceState.putInt("to",spinnertTo.getSelectedItemPosition());
savedInstanceState.putInt("radGroup1",resultGroup.getCheckedRadioButtonId());
savedInstanceState.putInt("radGroup2", valueGroup.getCheckedRadioButtonId());
super.onSaveInstanceState(savedInstanceState);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.unifiedlayout);
ButterKnife.bind(this);
//adapters for spinners
adapter1 = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_spinner_item,getResources().getStringArray( R.array.adapter_1) );
adapter2 = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_spinner_item,getResources().getStringArray(R.array. adapter_2));
adapter3 = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_spinner_item,getResources().getStringArray( R.array. adapter_3) );
adapter4 = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_spinner_item,getResources().getStringArray(R.array. adapter_4));}
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
resultView.setText(savedInstanceState.getString("result"));
valueEdit.setText(savedInstanceState.getString("value"));
spinnerFrom.setSelection(savedInstanceState.getInt("from"));
spinnertTo.setSelection(savedInstanceState.getInt("to"));
super.onSaveInstanceState(savedInstanceState);
}
//OnClick
@OnClick({R.id.button1, R.id.button2,R.id.button3,R.id.button4} )
public void setViewOnClickEvent(View view){
switch(view.getId()){
case R.id. button1:
fillSpinner(adapter1, adapter2); // fill spinner with values
break;
case R.id. button2:
fillSpinner(adapter3,
adapter4);
break;
//button for check if any adapter active
case R.id.buttonAdapter:
checkAdapter () ;
break;
}
}
//fill spinners when user checks radiobutton in radiogroups
protected void fillSpinner (final ArrayAdapter<String> spinnerToAdapter,
final ArrayAdapter<String> spinnerFromAdapter){
valueGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup valueGroup, int checkedId) {
pos = valueGroup.indexOfChild(findViewById(checkedId));
switch (pos) {
case 0:
spinnerFrom.setAdapter(spinnerToAdapter);
break;
case 1:
spinnerFrom.setAdapter(spinnerFromAdapter);
break;
}
}
});
resultGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup resultGroup, int checkedId) {
pos = resultGroup.indexOfChild(findViewById(checkedId));
switch (pos) {
case 0:
spinnertTo.setAdapter(spinnerToAdapter);
break;
case 1:
spinnertTo.setAdapter(spinnerFromAdapter);
break;
}
}
});
}
//simple method for check if both spinners has null value
protected void checkAdapter () {
//get Adapter from spinners
SpinnerAdapter valueAdapter = spinnerFrom.getAdapter();
SpinnerAdapter resultAdapter = spinnertTo.getAdapter();
if (valueAdapter == null | resultAdapter== null) {
Toast.makeText(this, “adapter null” , Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(this, “adapters not null” , Toast.LENGTH_SHORT).show();
}
}
编辑:答案并不完美,它还不能按我想要的方式工作,但这种方式让我有可能保存适配器: 1.Create 从适配器中检索要保存的字符串数组的方法:
public static String[] getStringArray(SpinnerAdapter adapter) {
String[] a = new String[adapter.getCount()];
for (int i = 0; i < a.length; i++)
a[i] = adapter.getItem(i).toString();
return a;
}
2.In onSavedInstanceState 放下一个代码:
// here i saving arraylist that ussualy i get from resources.
savedInstanceState.putStringArray(ADAPTER_TO,getStringArray(spinnerFrom.getAdapter()));
savedInstanceState.putStringArray(ADAPTER_FROM,getStringArray(spinnerFrom.getAdapter()));
3.In restoreInstance 创建新的适配器,它将用值填充您的微调器并使用 savedInstanceState.getStringArray(ADAPTER_TO) 填充保存的值:
toAdapter = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_spinner_item, savedInstanceState.getStringArray(ADAPTER_TO));
fromAdapter = new ArrayAdapter<>(getApplicationContext(), android.R.layout.simple_spinner_item, savedInstanceState.getStringArray(ADAPTER_FROM));
//use spinner.setAdapter to set created adapter.
spinnerFrom.setAdapter (fromAdapter)
spinnerTo.setAdapter (toAdapter)
这仍然无法正常工作,但如果您想在旋转屏幕上保存微调器状态,您可以尝试使用此逻辑。
Spinner 有 onNothingSelected()
方法。
在那个方法中,尝试玩 spinneradapter.getLastVisiblePosition()
.
当您关闭应用程序时,保存最后的位置,当您回来时,使用最后的位置。
希望对你有帮助。
您可以使用两种方法实现此目的。 1)(推荐)使用 ViewModels(架构组件)2) 使用保存和恢复状态。
1).您可以创建一个 viewModel,只要用户选择某项,就调用具有指定值的 ViewModel。通过观察 ViewModel,您可以获得该值的最新更改(即使在旋转更改之后),因为 ViewModel 将保持活动状态。
3) 将用户的选择保存在 activity 内的局部变量中,然后在保存和恢复中,put
和 get
您的值如下所示:
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putInt("firstSpinnerPosition", variableThatHasTheChangedPosition);
savedInstanceState.putInt("secondSpinnerPosition", variableThatHasTheChangedPositionForSecond);
// other stuff.
}
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
variableThatHasTheChangedPosition = savedInstanceState.getInt("firstSpinnerPosition");
variableThatHasTheChangedPositionForSecond = savedInstanceState.getInt("secondSpinnerPosition");
//notify your adapter of the changes
}