- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
当我使用 onRetainCustomNonConfigurationInstance 保存我的自定义 EditText 中包含的文本时,在我旋转设备后,最后一个 EditText 中包含的文本被复制到目标布局中的所有其他文本。
在断点调试的时候,发现所有的文本值一路都是正确的。但是在更改完成后,所有 EditText 都会显示相同的文本(最后一个的文本),并且焦点会转到布局中的第一个。
我在尽可能简单的项目中复制了这种行为。我尝试了 android API 级别 24 和 28。
这种行为从何而来,我该如何解决?
主要 Activity .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);}
/**
* Create a new custom editText with text
* @param text
*/
private void addEdit(String text){
CustomEdit newEdit;
if(text==null) newEdit = new CustomEdit(this, editList.size());
else newEdit = new CustomEdit(this, editList.size(),text);
layout.addView(newEdit,editList.size());
editList.add(newEdit);}
}
activity_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="20dp"
android:text="Title"
android:gravity ="center"/>
<HorizontalScrollView
android:id="@+id/scroll1"
android:layout_below="@id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingStart="10dp"
android:paddingLeft="10dp">
<LinearLayout
android:id="@+id/layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/add_button"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="+"/>
</LinearLayout>
</HorizontalScrollView>
</RelativeLayout>
自定义编辑器.java :
public class CustomEdit extends RelativeLayout {
private EditText editText;
private Button closeButton;
private int indexNumber;
public CustomEdit(Context context, int indexNumber) {
super(context);
this.indexNumber =indexNumber;
init();
}
public CustomEdit(Context context, int indexNumber, String text){
super(context);
this.indexNumber=indexNumber;
init();
editText.setText(text);
}
public CustomEdit(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CustomEdit(Context context, AttributeSet attrs, int defStyleAttr){
super(context, attrs, defStyleAttr);
init();
}
private void init(){
inflate(getContext(),R.layout.custom_edit_text,this);
editText = (EditText)findViewById(R.id.edit);
editText.setHint("EditText "+(indexNumber+1));
closeButton = (Button)findViewById(R.id.close_button);
closeButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
((MainActivity)getContext()).closeEdit(indexNumber);
}
});
}
public String getText(){
return editText.getText().toString();
}
}
自定义编辑文本.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="100dp"
android:layout_height="40dp">
<EditText
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/edit"
android:inputType="text"
android:hint="Element"
android:maxLength="30"/>
<Button
android:id="@+id/close_button"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignRight="@id/edit"
android:layout_alignEnd="@id/edit"
android:layout_alignTop="@id/edit"
android:text="X"/>
</RelativeLayout>
自定义保存.java :
public class CustomSave {
public ArrayList<String> texts;
CustomSave(ArrayList<String> texts){
this.texts = texts;
}
}
谢谢。
最佳答案
对于如何解决这个问题,您有两种选择:将您的代码移动到 Activity 生命周期中的不同点或更改 CustomEdit
的 xml 定义| .
将此代码移出 onCreate()
:
CustomSave data = (CustomSave)getLastCustomNonConfigurationInstance();
if(data==null) return;
for(int i = 0; i<data.texts.size();i++){
addEdit(data.texts.get(i));
}
并将其放入onRestoreInstanceState()
相反:
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
CustomSave data = (CustomSave)getLastCustomNonConfigurationInstance();
if(data==null) return;
for(int i = 0; i<data.texts.size();i++){
addEdit(data.texts.get(i));
}
}
或
将此属性添加到 <EditText>
在你的 custom_edit_text.xml
中标记文件:
android:saveEnabled="false"
您为保存/恢复文本值而编写的代码没有任何问题。但是,之后 onCreate()
,Android 会自动执行其自己的 保存/恢复逻辑,这会覆盖您所做的。
如果您从 onCreate()
移动您的代码至 onRestoreInstanceState()
,那么您的代码将在 Android 的自动保存/恢复后运行,因此您将“获胜”。或者,您可以通过添加 saveEnabled=false
来禁用自动保存/恢复属性。
Android 的自动保存/恢复不起作用的原因是它基于每个 View 的 android:id
。属性,还有你的 EditText
标签都具有相同的 ID。这意味着所有四个值都使用相同的键保存,因此最后一个值会覆盖所有以前的值。
关于java - OnRetainCustomConfigurationInstance 之后所有编辑文本中的重复文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52762930/
当我使用 onRetainCustomNonConfigurationInstance 保存我的自定义 EditText 中包含的文本时,在我旋转设备后,最后一个 EditText 中包含的文本被复制
我是一名优秀的程序员,十分优秀!