Как сохранить Spinner и его адаптер с помощью OnsavedInstance и восстановить его после? - PullRequest
0 голосов
/ 09 февраля 2019

У меня проблема с обработкой onSavedInstance и onRestoreInstance для двух моих счетчиков в приложении.

У меня есть два SpinnerAdapter, которые можно динамически заполнить парой ArrayAdapter<String> - adapter1 / adapter2и адаптер3 / адаптер4.

В приложении метода onCreate создайте для них 4 адаптера, когда пользователь нажимает button1, он заполняет spinnerFrom и spinnerTo с адаптером 1 и адаптером 2, когда button2 заполняет счетчики адаптером 3 и адаптером 4 соответственно.

Поскольку у меня небольшой жизненный цикл - когда экран вращается, андроид уничтожает приложение, а затем восстанавливает его с самого начала.

Итак, в 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. Создайте метод для извлечения массива строк из адаптера, который хотите «сохранить»:

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. В 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. В 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)

Это все еще не работает должным образом, как я хочу, но если вы хотите сохранить состояние счетчика на экране вращенияВы можете попробовать использовать эту логику.

Ответы [ 2 ]

0 голосов
/ 10 февраля 2019

Вы можете достичь этого двумя способами.1) (рекомендуется) Использование ViewModels (компоненты архитектуры) 2) использование состояния сохранения и восстановления.

1).Вы можете создать viewModel и всякий раз, когда пользователь выбирает что-либо, вызывать ViewModel с указанным значением.Наблюдая за ViewModel, вы можете получить последние изменения этого значения (даже после изменения ротации), потому что ViewModel останется живым.

3) Удерживайте выбор пользователя в локальной переменной внутри вашей деятельности, затем в сохранении и восстановлении.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

}
0 голосов
/ 10 февраля 2019

Spnner имеет метод onNothingSelected().
В этом методе попробуйте поиграть с spinneradapter.getLastVisiblePosition().
Когда вы выходите из приложения, сохраняете последнюю позицию, а когда вернетесь, используйте эту последнюю позицию.
Надеюсь, это поможет.

...