深入分析 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 changes
if (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);
}
@Override
public 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 activity
public void sendDataToActivity(String data) {
if (mListener != null) {
mListener.onFragmentInteraction(data);
}
}
}
在 Activity
中实现接口方法:
public class MyActivity extends AppCompatActivity implements MyFragment.OnFragmentInteractionListener {
@Override
public 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;
@Override
protected 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>() {
@Override
public void onChanged(@Nullable String item) {
// Update the UI
}
});
}
}
在 Fragment
中:
public class MyFragment extends Fragment {
private SharedViewModel viewModel;
@Override
public 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>() {
@Override
public 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
的交互、进程和线程模型、任务和返回栈管理、以及配置变化处理。理解这些关键概念和内部实现,有助于开发者创建高效、稳定和响应迅速的应用程序。通过灵活应用这些知识,可以提升应用程序的用户体验和性能。