在多个膨胀的EditTexts上设置文本会导致在旋转后使用相同的文本填充所有文本

pat*_*pat 5 android android-layout screen-rotation android-edittext layout-inflater

我正在膨胀一些EditTexts并将它们添加到LinearLayout:

private void setupCommentViews(){
    int i = 0;
        Iterator<CommentInformation> iterator = commentInformations.iterator();
    while(iterator.hasNext()) {
            i++;
            View v = LayoutInflater.from(context).inflate(R.layout.comment_row_item, commentsContainer, false);

            EditText commentField = (EditText)v.findViewById(R.id.comment);         

            CommentInformation commentInformation = iterator.next();
            final String uniqueId = commentInformation.getUniqueId();

            String currentCommentText = comments.get(uniqueId);         
            if(currentCommentText != null) {
                Log.v("into","Setting old text: "+currentCommentText);
                commentField.setText(currentCommentText);
            } else {
                Log.v("into","Setting empty text: "+i);
                commentField.setText("Setting empty text: "+i);
            }


            commentField.addTextChangedListener(new TextWatcher() {

                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {
                }

                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {

                }

                @Override
                public void afterTextChanged(Editable s) {
                    comments.put(uniqueId, s.toString().trim());
                }
            });

            commentsContainer.addView(v);
        }
}
Run Code Online (Sandbox Code Playgroud)

第一次运行后的日志如下所示:

04-01 17:40:41.244: V/into(28770): Setting empty text: 1
04-01 17:40:41.254: V/into(28770): Setting empty text: 2
04-01 17:40:41.254: V/into(28770): Setting empty text: 3
Run Code Online (Sandbox Code Playgroud)

并且所有EditTexts中都包含正确的文本("设置空文本:#")

-

我增加了TextChangedListenerEditText,我和膨胀文本时改变了我更新Map<String, String>,并把UNIQUEID为重点和注释文本作为值.

更改其中一条注释后旋转手机时会出现问题.我保存注释Map里面onSaveInstanceState:

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putSerializable(COMMENTS, (Serializable)comments);
}
Run Code Online (Sandbox Code Playgroud)

然后我在里面找回它们 onActivityCreated

if(savedInstanceState != null) {
        Log.v("into","Retrieving...");
        comments = (Map<String, String>)savedInstanceState.getSerializable(COMMENTS);
}
Run Code Online (Sandbox Code Playgroud)

我还迭代了这一点Map并验证是否有一个条目具有正确的uniqueId和正确更改的注释文本.

-

接下来我setupCommentViews()再打电话.这次日志看起来正确,但EditTextsALL与最后一个(最后一个膨胀的文本)具有相同的文本.

04-01 17:42:49.664: V/into(28770): Setting empty text: 1
04-01 17:42:49.664: V/into(28770): Setting old text: Changed the second textview
04-01 17:42:49.674: V/into(28770): Setting empty text: 3
Run Code Online (Sandbox Code Playgroud)

EditTexts现在所有人都说:"设置空文本:3"

使用ListView是不是我要找的,因为有大量的漏洞与解决方案EditTexts的内部ListViewAdjustResize softInputMode

-

任何人都可以了解这里发生的事情吗?

Bin*_*ran 14

默认情况下,当onSaveInstanceState调用活动的方法时,它还会通过视图层次结构并尝试保存任何视图的状态(如果可能),并在onRestoreInstanceState稍后调用活动方法时恢复这些视图状态.当调用每个View来保存状态时,我们可以在View类中看到这个方法:

protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
        if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
            mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
            Parcelable state = onSaveInstanceState();
            if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
                throw new IllegalStateException(
                        "Derived class did not call super.onSaveInstanceState()");
            }
            if (state != null) {
                // Log.i("View", "Freezing #" + Integer.toHexString(mID)
                // + ": " + state);
                container.put(mID, state);
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

从的EditText TextView的继承,在检查代码的TextView,我们看到的onSaveInstanceState方法返回当前文本和onRestoreInstanceState方法取回文字和显示.

现在,回到你的代码.你自己保存文本内容并在onCreate调用时恢复它,但是当onRestoreInstanceState调用Activity的方法时,EditText本身也会保存文本并恢复,这onCreate肯定会被调用,还有一件事,你的所有EditText都有相同的id,所以当视图层次结构被保存到SparseArray中,最后一个EditText状态(在本例中是文本内容)将覆盖所有以前的状态.这就是你的问题发生的原因.

解决方案:

  1. 你可以覆盖onRestoreInstanceState活动的方法,而不是调用super方法,这样你就可以阻止视图自动恢复它的状态,但我不认为这是个好主意,因为默认情况下可能还有其他东西需要恢复,不仅如此你的EditText
  2. 您可以将EditText的saveEnabled属性设置为false,这样它就不会恢复状态本身,我建议这样做.