[英]Application saving textbox state on orientation change?
我試圖了解Android應用程序的總體流程,並且遇到了我認為很奇怪的情況(注意:我對android編程非常陌生)。
我僅使用多行編輯文本字段制作了一個測試應用程序。 我在現場寫了1234。 沒有其他任何事情,對默認的Eclipse ADT制造的應用程序沒有其他更改,並且沒有在后端專門覆蓋任何內容,我改變了方向。 剩余的1234。 然后,我按下主頁按鈕,然后從最近的應用程序中將其打開。 剩余的1234。
我對應用程序生命周期的理解是,按下主屏幕按鈕后,該應用程序已停止並啟動,而當更改應用程序的方向時,該應用程序將被破壞並創建。 如果這是正確的,那么是否存在某種形式的自動狀態保持? 我當時的假設是,我必須從狀態束中取出各個變量,然后自己恢復它們。 那不正確嗎?
一個經驗豐富的Android開發人員可以對此做出的任何解釋都將是很棒的。 我一直在尋找合適的答案,但無濟於事。
MainActivity.java
package com.example.teststate;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
Activity_Main.xml
<RelativeLayout 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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.teststate.MainActivity" >
<EditText
android:id="@+id/editText1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginTop="30dp"
android:ems="10"
android:inputType="textMultiLine" >
<requestFocus />
</EditText>
</RelativeLayout>
Manifest.xml中的代碼段
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
謝謝!
發生這種情況的原因是,視圖通過覆蓋View#onSaveInstanceState()和View#onRestoreInstanceStance(Parcelable )來顯式保存並在方向更改時恢復其狀態。 這是TextView ( EditText的超類)中的實現。
@Override
public Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
// Save state if we are forced to
boolean save = mFreezesText;
int start = 0;
int end = 0;
if (mText != null) {
start = getSelectionStart();
end = getSelectionEnd();
if (start >= 0 || end >= 0) {
// Or save state if there is a selection
save = true;
}
}
if (save) {
SavedState ss = new SavedState(superState);
// XXX Should also save the current scroll position!
ss.selStart = start;
ss.selEnd = end;
if (mText instanceof Spanned) {
Spannable sp = new SpannableStringBuilder(mText);
if (mEditor != null) {
removeMisspelledSpans(sp);
sp.removeSpan(mEditor.mSuggestionRangeSpan);
}
ss.text = sp;
} else {
ss.text = mText.toString();
}
if (isFocused() && start >= 0 && end >= 0) {
ss.frozenWithFocus = true;
}
ss.error = getError();
return ss;
}
return superState;
}
[...]
@Override
public void onRestoreInstanceState(Parcelable state) {
if (!(state instanceof SavedState)) {
super.onRestoreInstanceState(state);
return;
}
SavedState ss = (SavedState)state;
super.onRestoreInstanceState(ss.getSuperState());
// XXX restore buffer type too, as well as lots of other stuff
if (ss.text != null) {
setText(ss.text);
}
if (ss.selStart >= 0 && ss.selEnd >= 0) {
if (mText instanceof Spannable) {
int len = mText.length();
if (ss.selStart > len || ss.selEnd > len) {
String restored = "";
if (ss.text != null) {
restored = "(restored) ";
}
Log.e(LOG_TAG, "Saved cursor position " + ss.selStart +
"/" + ss.selEnd + " out of range for " + restored +
"text " + mText);
} else {
Selection.setSelection((Spannable) mText, ss.selStart, ss.selEnd);
if (ss.frozenWithFocus) {
createEditorIfNeeded();
mEditor.mFrozenWithFocus = true;
}
}
}
}
if (ss.error != null) {
final CharSequence error = ss.error;
// Display the error later, after the first layout pass
post(new Runnable() {
public void run() {
setError(error);
}
});
}
}
如您所見,它將狀態保存在Parcelable
對象中,然后將其傳遞到新實例中具有相同android:id
的視圖中,並在新視圖上調用onRestoreInstanceState()
。 如果創建一個不僅僅包含其他視圖的自定義視圖,則可能需要覆蓋這些方法。
我無法為您提供代碼級別的說明。 但這是android承諾要做的事情之一。 您可以查看此重新創建活動
注意:為了使Android系統恢復您活動中視圖的狀態,每個視圖必須具有由android:id屬性提供的唯一ID。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.