螢幕旋轉預設會銷毀並重建 Activity(觸發 onDestroy → onCreate),導致 AsyncTask、執行緒、對話框等狀態遺失。若需鎖定直向/橫向或自行處理旋轉,可透過 Manifest 設定或程式碼控制。
<activity
android:name=".MainActivity"
android:screenOrientation="portrait" > <!-- 或 "landscape", "sensor", "user" -->
</activity>
優點:零代碼、系統自動處理。
缺點:使用者無法旋轉、平板/折疊機體驗差、無法適應多視窗。
<activity
android:name=".MainActivity"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden" >
</activity>
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
// 手動處理:切換佈局、調整視圖、更新資源
if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
// 橫向邏輯
} else {
// 直向邏輯
}
}
注意:API 13+ 必須包含 screenSize,否則旋轉仍會重建。
不阻止重建,而是妥善保存/恢復狀態:
// ViewModel 自動存活於配置變更
public class MyViewModel extends ViewModel {
private MutableLiveData<List<Item>> items = new MutableLiveData<>();
// 資料保持不變
}
// Activity
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
viewModel = new ViewModelProvider(this).get(MyViewModel.class);
// 觀察資料...
}
配合 onSaveInstanceState 保存 UI 狀態(捲動位置、輸入內容):
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("scrollPos", recyclerView.getScrollY());
outState.putString("inputText", editText.getText().toString());
}
@Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
editText.setText(savedInstanceState.getString("inputText"));
recyclerView.post(() -> recyclerView.scrollTo(0, savedInstanceState.getInt("scrollPos")));
}
| 方案 | 適用場景 | 優點 | 缺點 |
|---|---|---|---|
| 鎖定方向 | 遊戲、相機、全螢幕沉浸式 | 簡單、效能好 | 體驗死板、不適應新裝置 |
| configChanges | 影片播放器、地圖導航、複雜 Canvas 繪圖 | 保留實例、無重建開銷 | 需手動處理所有資源切換、易漏 |
| ViewModel + 狀態保存 | 絕大多數一般應用 | 架構清晰、自動生命週期、支援進程死後恢復 | 重建有微小開銷 |
AsyncTask 已棄用(API 30),旋轉時易洩漏 Context。請遷移至 Coroutine、RxJava 或 ExecutorService,並搭配 ViewModel 管理生命週期。
現代 Android 開發推薦「擁抱重建、妥善保存狀態」,而非強行阻止旋轉,能獲得更佳的裝置適應性與使用者體驗。