猿问

OnRetainCustomConfigurationInstance 之后所有 EditTexts

当我使用 onRetainCustomNonConfigurationInstance 保存包含在我的自定义 EditTexts 中的文本时,在我旋转设备后,最后一个 EditText 中包含的文本被复制到目标布局中的所有其他文本。


在用断点调试时,我发现所有的文本值一直都是正确的。但是在更改完成后,所有 EditText 都会显示相同的文本(来自最后一个的文本),并且焦点将分配给布局中的第一个。


我在最简单的项目中复制了这种行为。我尝试了 android API 级别 24 和 28。


这种行为来自哪里,我该如何解决?


主活动.java :


public class MainActivity extends AppCompatActivity {

    private ArrayList<CustomEdit> editList=new ArrayList<CustomEdit>();

    private LinearLayout layout;

    private Button addButton;


    @RequiresApi(api = Build.VERSION_CODES.M)

    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);


        addButton=findViewById(R.id.add_button);

        layout = findViewById(R.id.layout);


        addButton.setOnClickListener(new View.OnClickListener() {

            @Override

            public void onClick(View v) {

                addEdit();

            }

        });

        CustomSave data = (CustomSave)getLastCustomNonConfigurationInstance();

        if(data==null) return;


        for(int i = 0; i<data.texts.size();i++){

            addEdit(data.texts.get(i));

        }

    }

    @Override

    public Object onRetainCustomNonConfigurationInstance() {

        CustomSave data = save();

        return data;}


    private CustomSave save(){

        ArrayList<String> texts = new ArrayList<String>();

        for(int i =0; i<editList.size(); i++)

            texts.add(editList.get(i).getText());

        return new CustomSave(texts);}


    /**

     * Create a new custom EditText with hint

     */

    private void addEdit(){

        CustomEdit newEdit = new CustomEdit(this,editList.size());

        layout.addView(newEdit,editList.size());

        editList.add(newEdit);}


}


素胚勾勒不出你
浏览 175回答 2
2回答

aluckdog

对于如何解决此问题,您有两种选择:将代码移动到活动生命周期中的不同点或更改 .xml 的 xml 定义CustomEdit。安卓生命周期将此代码移出onCreate():CustomSave data = (CustomSave)getLastCustomNonConfigurationInstance();if(data==null) return;for(int i = 0; i<data.texts.size();i++){&nbsp; &nbsp; addEdit(data.texts.get(i));}并将其放入onRestoreInstanceState():@Overrideprotected void onRestoreInstanceState(Bundle savedInstanceState) {&nbsp; &nbsp; super.onRestoreInstanceState(savedInstanceState);&nbsp; &nbsp; CustomSave data = (CustomSave)getLastCustomNonConfigurationInstance();&nbsp; &nbsp; if(data==null) return;&nbsp; &nbsp; for(int i = 0; i<data.texts.size();i++){&nbsp; &nbsp; &nbsp; &nbsp; addEdit(data.texts.get(i));&nbsp; &nbsp; }}或者XML 定义将此属性添加到文件中的<EditText>标记custom_edit_text.xml:android:saveEnabled="false"您为保存/恢复文本值而编写的代码没有任何问题。但是,在 之后 onCreate(),Android 会自动执行自己的保存/恢复逻辑,这会覆盖您所做的。如果您将代码从 移动onCreate()到onRestoreInstanceState(),那么您的代码将在 Android 自动保存/恢复后运行,因此您将“获胜”。或者,您可以通过添加saveEnabled=false属性来禁用自动保存/恢复。Android 的自动保存/恢复不起作用的原因是它基于每个视图的android:id属性,并且您的EditText标签都具有相同的 id。这意味着所有四个值都使用相同的键保存,因此最后一个值会覆盖所有先前的值。

湖上湖

所以这里发生的事情是,Android 也在为您的自定义EditText实现处理状态保存,这会覆盖您的实现。由于您的CustomEdit实例列表是动态生成的,您可能不想依赖 Android 来保存视图的状态,因为它们没有唯一的 ID。由于您的CustomEdit膨胀custom_edit_text.xml(将EditTextID声明为@+id/edit),这意味着CustomEdit您添加到布局中的每个都具有相同的内部 ID&nbsp;EditText-&nbsp;R.id.edit。由于它们都具有相同的 ID,因此每个视图都会将其状态保存到该 ID,因此保存其状态的最后一个将最终成为恢复状态时应用于所有视图的文本。您可以做两件事来避免这种情况:在你的custom_edit_text.xml,添加android:saveEnabled="false"到EditText。这将阻止View保存that的状态。这将是首选,因为它避免了做不必要的工作。在onRestoreInstanceState()当前正在恢复视图状态的位置执行状态恢复。
随时随地看视频慕课网APP

相关分类

Java
我要回答