Как сохранить состояние нескольких EditTexts (чтобы избежать ротации мобильного пользователя), которые были созданы во время выполнения при нажатии кнопки? - PullRequest
0 голосов
/ 21 апреля 2020

Мое приложение получает введенный номер из EditText, когда пользователь нажимает кнопку «ОК». Затем некоторые EditTexts создаются на основе этого входного номера. Но когда пользователь поворачивает экран, вновь / динамически созданные EditTexts удаляются, и я хочу сохранить его, когда пользователь поворачивает экран.

Я использовал onSaveInstanceState() и onRestoreInstanceState(), чтобы сохранить состояние EditTexts, но это не так не работает (приложение вылетает при повороте телефона). Может быть, я не смог правильно использовать эти методы.

Я даю свой xml и java код:

Мой xml код:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:padding="5dp"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Enter No of EditText:"
        android:textSize="24sp"
        android:textColor="@color/colorPrimaryDark"/>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <EditText
            android:id="@+id/edtNoCreate"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:hint="No of EditText"
            android:inputType="number"/>

        <Button
            android:id="@+id/btnCreate"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="OKAY"/>

    </LinearLayout>


    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:background="#EDE9E9">

        <LinearLayout
            android:id="@+id/lnrDynamicEditTextHolder"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

        </LinearLayout>

    </ScrollView>


</LinearLayout>

Мой java код:

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.*;
import android.widget.*;
import java.util.*;
import static java.lang.Integer.parseInt;

public class MainActivity extends AppCompatActivity {

    private LinearLayout lnrDynamicEditTextHolder;
    private EditText edtNoCreate;
    private Button btnCreate;

    List<EditText> allEditText = new ArrayList<EditText>();

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

        lnrDynamicEditTextHolder = (LinearLayout) findViewById(R.id.lnrDynamicEditTextHolder);
        btnCreate = (Button) findViewById(R.id.btnCreate);
        edtNoCreate = (EditText) findViewById(R.id.edtNoCreate);

        btnCreate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try{
                    if(edtNoCreate.getText().toString().length()>0 && parseInt(edtNoCreate.getText().toString())!=0) {
                        if(edtNoCreate.getText().toString().length()==0){
                            edtNoCreate.setError("This Item Cannot be Empty");
                            return;
                        }
                        allEditText.clear();
                        lnrDynamicEditTextHolder.removeAllViews();

                        int length = parseInt(edtNoCreate.getText().toString());

                        for (int i=0;i<length;i++){
                            EditText editText = new EditText(MainActivity.this);
                            editText.setId(i+1);
                            editText.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
                            allEditText.add(editText);
                            lnrDynamicEditTextHolder.addView(editText);
                        }
                    }
                } catch (Throwable e) {
                    e.printStackTrace();
                    edtNoCreate.setError("This Item Cannot be Empty");
                }
            }
        });
    }


    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        super.onSaveInstanceState(savedInstanceState);

        int mViewsCount = 0;
        for(EditText view : allEditText)
        {
            savedInstanceState.putInt("mViewId_" + mViewsCount, view.getId());
            mViewsCount++;
        }

        savedInstanceState.putInt("mViewsCount", mViewsCount);
    }

    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);

        int mViewsCount = savedInstanceState.getInt("mViewsCount");;
        for(int i = 0; i <= mViewsCount; i++)
        {
            EditText view = allEditText.get(i);

            int viewId = savedInstanceState.getInt("mViewId_" + i);
            view.setId(viewId);

            mViewsCount++;
        }
    }
}

Ответы [ 3 ]

0 голосов
/ 21 апреля 2020

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

<activity android:name=".YourActiyvity"
      android:configChanges="orientation">

для более подробной информации читайте это

0 голосов
/ 21 апреля 2020

Оба существующих ответа с использованием ViewModels и ручной обработки configChange действительно помогают.

Однако лично я был бы осторожен с настройкой configChanges в манифесте. Даже документация предупреждает:

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

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

В любом случае, вот как я справлюсь с этим в вашей ситуации:

  • Прежде всего сохраните идентификаторы ваших EditText в ArrayList<Int>
  • При добавлении нового EditText просто установите свой идентификатор в размер вашего списка идентификаторов и добавьте элемент в список со значением его размера
  • Затем в onSaveInstanceState добавьте эти идентификаторы в свой набор сохраненных файлов InstanceState (используя функцию putIntegerArrayList таким образом, вам не нужно сохранять каждый идентификатор отдельно)
  • В onCreate просто проверьте, является ли SavedInstanceState нулевым или нет
  • Если значение параметра saveInstanceState не нулевое, получите идентификаторы из него и выполните итерацию по ним, создавая EditText для каждого идентификатора (так же, как при нажатии кнопки)
  • Это все, что нужно сделать :)

Так же, как крошечная справочная информация: при вращении устройства , действие воссоздается, что означает, что все программно добавленные представления «пропали» (поскольку макет снова раздувается). Но если вы добавите эти виды с соответствующим идентификатором снова, состояние сохранится.

Достаточно поговорить здесь:

public class MainActivity extends AppCompatActivity {

    private LinearLayout lnrDynamicEditTextHolder;
    private EditText edtNoCreate;
    private Button btnCreate;
    private static final String KEY_IDS = "IDS";

    List<EditText> allEditText = new ArrayList<EditText>();
    ArrayList<Integer> allIds = new ArrayList<Integer>();

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

        lnrDynamicEditTextHolder = (LinearLayout) findViewById(R.id.lnrDynamicEditTextHolder);
        btnCreate = (Button) findViewById(R.id.btnCreate);
        edtNoCreate = (EditText) findViewById(R.id.edtNoCreate);

        if (savedInstanceState != null) {
            allIds = savedInstanceState.getIntegerArrayList(KEY_IDS)

            for (int i=0;i<allIds.size();i++){
                EditText editText = new EditText(MainActivity.this);
                editText.setId(allIds.get(i));
                editText.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
                allEditText.add(editText);
                lnrDynamicEditTextHolder.addView(editText);
            }
        }

        btnCreate.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try{
                    if(edtNoCreate.getText().toString().length()>0 && parseInt(edtNoCreate.getText().toString())!=0) {
                        if(edtNoCreate.getText().toString().length()==0){
                            edtNoCreate.setError("This Item Cannot be Empty");
                            return;
                        }
                        allEditText.clear();
                        lnrDynamicEditTextHolder.removeAllViews();

                        int length = parseInt(edtNoCreate.getText().toString());

                        for (int i=0;i<length;i++){
                            EditText editText = new EditText(MainActivity.this);
                            editText.setId(allIds.size());
                            allIds.add(allIds.size());
                            editText.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
                            allEditText.add(editText);
                            lnrDynamicEditTextHolder.addView(editText);
                        }
                    }
                } catch (Throwable e) {
                    e.printStackTrace();
                    edtNoCreate.setError("This Item Cannot be Empty");
                }
            }
        });
    }


    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        super.onSaveInstanceState(savedInstanceState);
        savedInstanceState.putIntegerArrayList(KEY_IDS, allIds);
    }
}
0 голосов
/ 21 апреля 2020

вы должны изучить возможность включения ViewModels в свои приложения. ViewModels может сохранить состояние действия или фрагмента из onDeviceConfigurationChange (помимо других изменений конфигурации). Все, что вам нужно сделать, это попросить любую ViewModel вы хотите от ViewModelProviders ().

ViewModels в android

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...