片段 - 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 EditTexts 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

  1. onAttach(Activity) called once the fragment is associated with its activity.
  2. onCreate(Bundle) called to do initial creation of the fragment.
  3. onCreateView(LayoutInflater, ViewGroup, Bundle) creates and returns the view hierarchy associated with the fragment.
  4. onActivityCreated(Bundle) tells the fragment that its activity has completed its own Activity.onCreate().
  5. onViewStateRestored(Bundle) tells the fragment that all of the saved state of its view hierarchy has been restored.
  6. onStart() makes the fragment visible to the user (based on its containing activity being started).
  7. 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 在屏幕方向上保持数据状态已更改