2017-08-13 65 views
1

我在Android Studio中創建了一個示例應用程序,以瞭解Android應用程序的生命週期。我知道方向改變完全重新開始活動(即再次調用OnCreate方法)。 據我所知,方向改變應該已經破壞了上下文,並在設備旋轉後顯示一個空白文本。但不知怎的,沒有重寫onSaveInstanceState和onRestoreInstanceState方法,它保存了上下文。EditText自動保存設備旋轉後的值

我沒有任何碎片。它只是Android Studio提供的基本模板,幾乎沒有重載的生命週期方法。 這裏是我的MainActivity類別:

package com.example.android.a2_screen_orientation_change; 

import android.os.Bundle; 
import android.support.v7.app.AppCompatActivity; 
import android.util.Log; 

public class MainActivity extends AppCompatActivity { 

    private static final String TAG = MainActivity.class.getSimpleName(); 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
    } 

    @Override 
    protected void onStart() { 
     super.onStart(); 
     Log.i(TAG, "in method onStart"); 
    } 

    @Override 
    protected void onResume() { 
     super.onResume(); 
     Log.i(TAG, "in method onResume"); 
    } 

    @Override 
    protected void onRestart() { 
     super.onRestart(); 
     Log.i(TAG, "in method onRestart"); 
    } 

    @Override 
    protected void onPause() { 
     super.onPause(); 
     Log.i(TAG, "in method onPause"); 
    } 

    @Override 
    protected void onStop() { 
     super.onStop(); 
     Log.i(TAG, "in method onStop"); 
    } 

    @Override 
    protected void onDestroy() { 
     super.onDestroy(); 
     Log.i(TAG, "in method onDestroy"); 
    } 
} 

佈局:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:context="com.example.android.a2_screen_orientation_change.MainActivity"> 

    <EditText 
     android:id="@+id/editText" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" /> 

</LinearLayout> 

AbdroidManifest:

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.example.android.a2_screen_orientation_change"> 

    <application 
     android:allowBackup="true" 
     android:icon="@mipmap/ic_launcher" 
     android:label="@string/app_name" 
     android:roundIcon="@mipmap/ic_launcher_round" 
     android:supportsRtl="true" 
     android:theme="@style/AppTheme"> 
     <activity android:name=".MainActivity"> 
      <intent-filter> 
       <action android:name="android.intent.action.MAIN" /> 

       <category android:name="android.intent.category.LAUNCHER" /> 
      </intent-filter> 
     </activity> 
    </application> 

</manifest> 

圖片: Text got saved even after device orientation change

+0

這個活動怎麼樣是導致您認爲國家是不會回到原點?請在你的問題中列出這樣的狀態。 –

+0

等待,我將添加截圖 –

+0

'EditText's自動保存/恢復保存狀態包中的文本。你不需要做任何事情就可以發生。 https://developer.android.com/reference/android/widget/TextView.html#setFreezesText(boolean)(注意「冰柱」是保存狀態包的舊術語。) –

回答

2

由於EditText是一個聚焦視圖,所以在PhoneWindow中,它的狀態將自動保存在saveHierarchyState()方法中。你可以看到代碼:

@Override 
public Bundle saveHierarchyState() { 
    Bundle outState = new Bundle(); 
    if (mContentParent == null) { 
     return outState; 
    } 
    SparseArray<Parcelable> states = new SparseArray<Parcelable>(); 
    mContentParent.saveHierarchyState(states); 
    outState.putSparseParcelableArray(VIEWS_TAG, states); 
    // save the focused view id 
    View focusedView = mContentParent.findFocus(); 
    if (focusedView != null) { 
     if (focusedView.getId() != View.NO_ID) { 
      outState.putInt(FOCUSED_ID_TAG, focusedView.getId()); 
     } else { 
      if (false) { 
       Log.d(TAG, "couldn't save which view has focus because the focused view " 
         + focusedView + " has no id."); 
      } 
     } 
    } 
    // save the panels 
    SparseArray<Parcelable> panelStates = new SparseArray<Parcelable>(); 
    savePanelState(panelStates); 
    if (panelStates.size() > 0) { 
     outState.putSparseParcelableArray(PANELS_TAG, panelStates); 
    } 
    if (mActionBar != null) { 
     outState.putBoolean(ACTION_BAR_TAG, mActionBar.isOverflowMenuShowing()); 
    } 
    return outState; 
} 

和代碼TextView

@Override 
public Parcelable onSaveInstanceState() { 
    Parcelable superState = super.onSaveInstanceState(); 
    // Save state if we are forced to 
    final boolean freezesText = getFreezesText(); 
    boolean hasSelection = false; 
    int start = -1; 
    int end = -1; 
    if (mText != null) { 
     start = getSelectionStart(); 
     end = getSelectionEnd(); 
     if (start >= 0 || end >= 0) { 
      // Or save state if there is a selection 
      hasSelection = true; 
     } 
    } 
    if (freezesText || hasSelection) { 
     SavedState ss = new SavedState(superState); 
     if (freezesText) { 
      if (mText instanceof Spanned) { 
       final Spannable sp = new SpannableStringBuilder(mText); 
       if (mEditor != null) { 
        removeMisspelledSpans(sp); 
        sp.removeSpan(mEditor.mSuggestionRangeSpan); 
       } 
       ss.text = sp; 
      } else { 
       ss.text = mText.toString(); 
      } 
     } 
     if (hasSelection) { 
      // XXX Should also save the current scroll position! 
      ss.selStart = start; 
      ss.selEnd = end; 
     } 
     if (isFocused() && start >= 0 && end >= 0) { 
      ss.frozenWithFocus = true; 
     } 
     ss.error = getError(); 
     if (mEditor != null) { 
      ss.editorState = mEditor.saveInstanceState(); 
     } 
     return ss; 
    } 
    return superState; 
} 

所以,如果你刪除EditTextView的ID在XML文件中:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:context="com.example.android.a2_screen_orientation_change.MainActivity"> 

    <EditText 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" /> 

</LinearLayout> 

你會看你想要什麼! (從@Mike M.坦克的補充)

+0

謝謝,我試過,它的工作。 有趣的行爲! –

+0

的確,刪除ID會導致EditText不保存它的文本,但你所引用的saveHierarchyState()方法與此無關。所有該方法正在做 - 就EditText而言 - 正在保存其ID,因此當層次結構恢復時,同一個ID將被賦予焦點。它與文本無關。 –

+0

@MikeM。這是真的,謝謝你的正確! – vesper

1

Android是在默認情況下,恢復了一些狀態視圖。 在Layout xml中,將android:saveEnabled="false"添加到EditText。而EditText的值將不會被保留。

+0

我看到一些教程,其中文字在方向更改後丟失。 在較新版本的Android中添加了此默認行爲嗎? –

+0

根據Android參考,此行爲似乎沒有從默認更改。但是,如果要刷新(清除)視圖的數據,則必須將此屬性設置爲false。 https://developer.android.com/reference/android/R.attr.html#saveEnabled –

1

Android的自動處理節電狀態&恢復,直到你明確指定

android:configChanges="orientation" 
在mainifest

在情況下,你沒有一個id

對於UI元素,Android將無法恢復元素的狀態。

請參考這裏的答案 https://stackoverflow.com/a/19234974/1099156