片段 - EditText.setText(String) 在字符串来自 savedInstanceState 时不起作用,但在硬编码时起作用
fragment - EditText.setText(String) not working when string comes from savedInstanceState but works when hard coded
我有一个片段:
ContactUsFragment.java
import android.app.Activity;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.app.Fragment;
import android.support.design.widget.TextInputLayout;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.Toast;
/**
*
*/
public class ContactUsFragment extends Fragment {
private EditText et_name, et_phoneno;
private String name = "", phone = "";
private boolean instanceSaved = false;
public ContactUsFragment() {
// Required empty public constructor
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState != null) {
Toast.makeText(getActivity().getBaseContext(), "Not null", Toast.LENGTH_LONG).show();
name = savedInstanceState.getString("sv_name");
phone = savedInstanceState.getString("sv_phone");
instanceSaved = savedInstanceState.getBoolean("InstanceSaved");
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_contact_us, container, false);
registerETs(view);
if(instanceSaved) {
Toast.makeText(getActivity().getBaseContext(), "Instance was saved", Toast.LENGTH_LONG).show();
Toast.makeText(getActivity().getBaseContext(), name, Toast.LENGTH_LONG).show(); //--This line works. Gives the correct value of string upon orientation change--
Toast.makeText(getActivity().getBaseContext(), phone, Toast.LENGTH_LONG).show();
et_name.setText(name); //--This line does not work--
et_name.setText("Another String"); //--This line does not work--
et_phoneno.setText(phone); //--This line does not work--
}
et_name.setText("A String"); //--This line works--
return view;
}
@Override
public void onStart() {
super.onStart();
}
public void registerETs(View view) {
et_name = (EditText)view.findViewById(R.id.input_name);
et_phoneno = (EditText)view.findViewById(R.id.input_phoneno);
}
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
Toast.makeText(getActivity().getBaseContext(), "saving", Toast.LENGTH_LONG).show();
savedInstanceState.putString("sv_name", et_name.getText().toString());
savedInstanceState.putString("sv_phone", et_phoneno.getText().toString());
savedInstanceState.putBoolean("InstanceSaved", true);
}
}
我面临的问题是,if(instanceSaved){...}
中的 et_name.setText(name)
不起作用。它什么也没设置。就好像,name 正在从 if(savedInstanceSaved != null){...}
中获取 null
值。但是我在各种代码块中使用的 Toasts
正在按预期工作。它正在 onSaveInstanceState(Bundle savedInstanceState){...}
中保存,执行 if(savedInstanceSaved != null){...}
,这意味着我的 savedInstanceState
不为空,并且还在 if(instanceSaved){...}
中显示 name
字符串的正确值。这意味着我的代码在 orientation
更改期间正常工作。但它没有在 setText(String)
方法中设置任何文本。
我也试过使用 setText("String")
,效果很好。如代码所示。我做错了什么,我错过了什么?请帮忙。谢谢。
NOTE:
I am using EditText
s inside android.support.design.widget.TextInputLayout
EDIT:
I found that no matter what, setText(name)
is always taking the initial value of String name
. Even though name
in Toast
shows the new updated value, setText()
is somehow always using the initial value.
Also, I noticed that if I change the orientation thrice, the app crashes.
如果您的视图有 ID(它们确实有),那么 Android 将自动恢复视图状态。这发生在 onCreateView()
之后。所以您的代码正在运行,您的更改只是丢失了。
详细说明,引用official Fragment documentation:
- onAttach(Activity) called once the fragment is associated with its activity.
- onCreate(Bundle) called to do initial creation of the fragment.
- onCreateView(LayoutInflater, ViewGroup, Bundle) creates and returns the view hierarchy associated with the fragment.
- onActivityCreated(Bundle) tells the fragment that its activity has completed its own Activity.onCreate().
- onViewStateRestored(Bundle) tells the fragment that all of the saved state of its view hierarchy has been restored.
- onStart() makes the fragment visible to the user (based on its containing activity being started).
- onResume() makes the fragment begin interacting with the user (based on its containing activity being resumed).
更新:
根据您在下方的评论,我有 99% 的把握认为问题出在您显示的代码之外。你的问题是你在内存中有两个 ContactUsFragment
的副本。
已恢复其状态的一个,包括 EditText
的文本,然后是您必须重新创建的另一个。因此,您会看到 toast 弹出窗口(因为旧片段已恢复),但您看不到放在 EditText
中的值,因为您已将旧片段的视图替换为新的 ContactUsFragment
的观点,尚未恢复。
我尝试了很多东西,但最终,我得到了非常简单的解决方案..在我们知道 android 主要使用视图 id
的 RestoreInstanceState 和 onSaveInstanceState 之前
<android.support.design.widget.TextInputLayout
android:id="@+id/ids1"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/ids2"
android:layout_width="match_parent"
android:layout_height="wrap_content"/></android.support.design.widget.TextInputLayout>
为两个视图分配 id ..现在 android 在屏幕方向上保持数据状态已更改
我有一个片段:
ContactUsFragment.java
import android.app.Activity;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.app.Fragment;
import android.support.design.widget.TextInputLayout;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.Toast;
/**
*
*/
public class ContactUsFragment extends Fragment {
private EditText et_name, et_phoneno;
private String name = "", phone = "";
private boolean instanceSaved = false;
public ContactUsFragment() {
// Required empty public constructor
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState != null) {
Toast.makeText(getActivity().getBaseContext(), "Not null", Toast.LENGTH_LONG).show();
name = savedInstanceState.getString("sv_name");
phone = savedInstanceState.getString("sv_phone");
instanceSaved = savedInstanceState.getBoolean("InstanceSaved");
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_contact_us, container, false);
registerETs(view);
if(instanceSaved) {
Toast.makeText(getActivity().getBaseContext(), "Instance was saved", Toast.LENGTH_LONG).show();
Toast.makeText(getActivity().getBaseContext(), name, Toast.LENGTH_LONG).show(); //--This line works. Gives the correct value of string upon orientation change--
Toast.makeText(getActivity().getBaseContext(), phone, Toast.LENGTH_LONG).show();
et_name.setText(name); //--This line does not work--
et_name.setText("Another String"); //--This line does not work--
et_phoneno.setText(phone); //--This line does not work--
}
et_name.setText("A String"); //--This line works--
return view;
}
@Override
public void onStart() {
super.onStart();
}
public void registerETs(View view) {
et_name = (EditText)view.findViewById(R.id.input_name);
et_phoneno = (EditText)view.findViewById(R.id.input_phoneno);
}
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
Toast.makeText(getActivity().getBaseContext(), "saving", Toast.LENGTH_LONG).show();
savedInstanceState.putString("sv_name", et_name.getText().toString());
savedInstanceState.putString("sv_phone", et_phoneno.getText().toString());
savedInstanceState.putBoolean("InstanceSaved", true);
}
}
我面临的问题是,if(instanceSaved){...}
中的 et_name.setText(name)
不起作用。它什么也没设置。就好像,name 正在从 if(savedInstanceSaved != null){...}
中获取 null
值。但是我在各种代码块中使用的 Toasts
正在按预期工作。它正在 onSaveInstanceState(Bundle savedInstanceState){...}
中保存,执行 if(savedInstanceSaved != null){...}
,这意味着我的 savedInstanceState
不为空,并且还在 if(instanceSaved){...}
中显示 name
字符串的正确值。这意味着我的代码在 orientation
更改期间正常工作。但它没有在 setText(String)
方法中设置任何文本。
我也试过使用 setText("String")
,效果很好。如代码所示。我做错了什么,我错过了什么?请帮忙。谢谢。
NOTE: I am using
EditText
s insideandroid.support.design.widget.TextInputLayout
EDIT: I found that no matter what,
setText(name)
is always taking the initial value ofString name
. Even thoughname
inToast
shows the new updated value,setText()
is somehow always using the initial value. Also, I noticed that if I change the orientation thrice, the app crashes.
如果您的视图有 ID(它们确实有),那么 Android 将自动恢复视图状态。这发生在 onCreateView()
之后。所以您的代码正在运行,您的更改只是丢失了。
详细说明,引用official Fragment documentation:
- onAttach(Activity) called once the fragment is associated with its activity.
- onCreate(Bundle) called to do initial creation of the fragment.
- onCreateView(LayoutInflater, ViewGroup, Bundle) creates and returns the view hierarchy associated with the fragment.
- onActivityCreated(Bundle) tells the fragment that its activity has completed its own Activity.onCreate().
- onViewStateRestored(Bundle) tells the fragment that all of the saved state of its view hierarchy has been restored.
- onStart() makes the fragment visible to the user (based on its containing activity being started).
- onResume() makes the fragment begin interacting with the user (based on its containing activity being resumed).
更新:
根据您在下方的评论,我有 99% 的把握认为问题出在您显示的代码之外。你的问题是你在内存中有两个 ContactUsFragment
的副本。
已恢复其状态的一个,包括 EditText
的文本,然后是您必须重新创建的另一个。因此,您会看到 toast 弹出窗口(因为旧片段已恢复),但您看不到放在 EditText
中的值,因为您已将旧片段的视图替换为新的 ContactUsFragment
的观点,尚未恢复。
我尝试了很多东西,但最终,我得到了非常简单的解决方案..在我们知道 android 主要使用视图 id
的 RestoreInstanceState 和 onSaveInstanceState 之前<android.support.design.widget.TextInputLayout
android:id="@+id/ids1"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/ids2"
android:layout_width="match_parent"
android:layout_height="wrap_content"/></android.support.design.widget.TextInputLayout>
为两个视图分配 id ..现在 android 在屏幕方向上保持数据状态已更改