深入分析 Android Activity (三)
1. Activity 的配置變化處理
當設備配置(如屏幕方向、語言、屏幕大小等)發生變化時,默認情況下,Android 會銷毀并重新創建當前的 Activity
。這種行為確保了新配置能夠正確應用,但在某些情況下,重新創建 Activity
會帶來性能問題或不必要的復雜性。
可以通過 android:configChanges
屬性來指定當特定配置變化發生時,不銷毀 Activity
,而是調用 onConfigurationChanged
方法。
1.1 處理配置變化
在 AndroidManifest.xml
文件中聲明需要處理的配置變化:
<activity android:name=".MyActivity"android:configChanges="orientation|screenSize|keyboardHidden">
</activity>
在 Activity
中覆蓋 onConfigurationChanged
方法以處理配置變化:
@Override
public void onConfigurationChanged(Configuration newConfig) {super.onConfigurationChanged(newConfig);// Handle configuration changesif (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {// Handle landscape orientation} else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {// Handle portrait orientation}
}
2. Activity 的存儲和恢復狀態
為了在配置變化、進程被終止或其他情況發生時保存和恢復 Activity
的狀態,可以使用 onSaveInstanceState
和 onRestoreInstanceState
方法。
2.1 保存狀態
onSaveInstanceState
方法在 Activity
即將被銷毀時調用,用于保存臨時狀態信息:
@Override
protected void onSaveInstanceState(Bundle outState) {super.onSaveInstanceState(outState);outState.putString("key", "value");
}
2.2 恢復狀態
onRestoreInstanceState
方法在 Activity
被重新創建后調用,用于恢復之前保存的狀態信息:
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {super.onRestoreInstanceState(savedInstanceState);String value = savedInstanceState.getString("key");
}
也可以在 onCreate
方法中恢復狀態:
@Override
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);if (savedInstanceState != null) {String value = savedInstanceState.getString("key");}
}
3. Activity 與 Fragment 的通信
Fragment
是一個可重用的 UI 組件,能夠在 Activity
中管理部分 UI 和邏輯。Fragment
可以獨立于 Activity
管理自己的生命周期和狀態。
3.1 通過接口進行通信
Activity
和 Fragment
之間可以通過接口進行通信。在 Fragment
中定義一個接口,并在 Activity
中實現它:
public class MyFragment extends Fragment {private OnFragmentInteractionListener mListener;public interface OnFragmentInteractionListener {void onFragmentInteraction(String data);}@Overridepublic void onAttach(Context context) {super.onAttach(context);if (context instanceof OnFragmentInteractionListener) {mListener = (OnFragmentInteractionListener) context;} else {throw new RuntimeException(context.toString() + " must implement OnFragmentInteractionListener");}}// Call this method to send data to the activitypublic void sendDataToActivity(String data) {if (mListener != null) {mListener.onFragmentInteraction(data);}}
}
在 Activity
中實現接口方法:
public class MyActivity extends AppCompatActivity implements MyFragment.OnFragmentInteractionListener {@Overridepublic void onFragmentInteraction(String data) {// Handle interaction with the fragment}
}
3.2 通過 ViewModel 進行通信
使用 ViewModel
和 LiveData
可以在 Activity
和 Fragment
之間進行數據共享和通信,尤其是在 MVVM 架構中:
public class SharedViewModel extends ViewModel {private final MutableLiveData<String> selected = new MutableLiveData<String>();public void select(String item) {selected.setValue(item);}public LiveData<String> getSelected() {return selected;}
}
在 Activity
中:
public class MyActivity extends AppCompatActivity {private SharedViewModel viewModel;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);viewModel = new ViewModelProvider(this).get(SharedViewModel.class);viewModel.getSelected().observe(this, new Observer<String>() {@Overridepublic void onChanged(@Nullable String item) {// Update the UI}});}
}
在 Fragment
中:
public class MyFragment extends Fragment {private SharedViewModel viewModel;@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {View view = inflater.inflate(R.layout.fragment_my, container, false);viewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);viewModel.getSelected().observe(getViewLifecycleOwner(), new Observer<String>() {@Overridepublic void onChanged(@Nullable String item) {// Update the UI}});return view;}
}
4. Activity 的窗口管理和視圖層次結構
4.1 DecorView
DecorView
是 Activity
窗口中的最頂層視圖容器,包含了狀態欄、標題欄和內容區域。Window
類通過 setContentView
將視圖層次結構添加到 DecorView
中。
@Override
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);
}
4.2 Window 和 WindowManager
Window
是一個抽象類,表示一個頂級窗口。在大多數情況下,Activity
使用 PhoneWindow
類,它是 Window
的具體實現。WindowManager
是一個系統服務,負責管理窗口。
通過 Window
和 WindowManager
可以控制窗口的布局參數:
Window window = getWindow();
WindowManager.LayoutParams params = window.getAttributes();
params.height = WindowManager.LayoutParams.MATCH_PARENT;
params.width = WindowManager.LayoutParams.MATCH_PARENT;
window.setAttributes(params);
5. Activity 的任務和返回棧(Back Stack)
Android 使用任務和返回棧來管理 Activity
的導航。每個任務由一個棧(返回棧)來管理 Activity
。
5.1 啟動 Activity 的 Intent 標志
可以使用 Intent
標志來控制 Activity
的啟動行為和返回棧。例如:
FLAG_ACTIVITY_NEW_TASK
:在新的任務中啟動Activity
。FLAG_ACTIVITY_CLEAR_TOP
:如果目標Activity
已經在棧中存在,則將其上面的所有Activity
清除。
Intent intent = new Intent(this, MyActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
5.2 處理返回棧中的數據
可以使用 onActivityResult
方法處理從另一個 Activity
返回的數據:
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {super.onActivityResult(requestCode, resultCode, data);if (requestCode == REQUEST_CODE && resultCode == RESULT_OK) {String result = data.getStringExtra("key");// Handle the result}
}
在啟動 Activity
時可以傳遞請求代碼:
Intent intent = new Intent(this, AnotherActivity.class);
startActivityForResult(intent, REQUEST_CODE);
總結
Android 的 Activity
設計涉及生命周期管理、啟動模式、視圖層次結構、與 Fragment
的交互、進程和線程模型、任務和返回棧管理、以及配置變化處理。理解這些關鍵概念和內部實現,有助于開發者創建高效、穩定和響應迅速的應用程序。通過靈活應用這些知識,可以提升應用程序的用戶體驗和性能。