1. 为什么需要封装BaseActivity?
在Android应用开发中,Activity作为四大组件之一承载着用户交互的核心功能。但原生Activity类提供的功能相当基础,实际项目中我们往往需要重复实现以下功能:
- 统一的标题栏管理
- 权限申请处理
- 网络状态监听
- 数据加载动画
- 通用对话框封装
- 页面跳转动画
- 生命周期监控
以权限申请为例,传统实现方式需要在每个Activity中重写onRequestPermissionsResult方法,导致代码重复率高达70%以上。而通过基类封装,我们只需要在BaseActivity中实现一次,所有子类即可通过简洁的接口调用。
2. 基础框架搭建
2.1 类结构设计
java复制public abstract class BaseActivity extends AppCompatActivity {
// 通用功能实现区
protected void initSystemUI() {...}
protected void handlePermissions(...) {...}
// 抽象方法约束区
protected abstract int getLayoutId();
protected abstract void initViews();
protected abstract void initData();
// 生命周期增强区
@Override
protected void onCreate(...) {
super.onCreate(...);
setContentView(getLayoutId());
initSystemUI();
initViews();
initData();
}
}
这种设计实现了:
- 强制子类实现必要方法(getLayoutId等)
- 自动执行通用初始化流程
- 保留Activity原生生命周期
2.2 基础功能封装
统一异常处理方案:
java复制protected void safeRun(Runnable task) {
try {
task.run();
} catch (Exception e) {
Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT).show();
Log.e("BaseActivity", e.getMessage(), e);
}
}
典型调用场景:
java复制// 传统写法
try {
loadNetworkData();
} catch (Exception e) {
handleError(e);
}
// 基类优化后
safeRun(() -> loadNetworkData());
3. 高级功能实现
3.1 智能权限管理
java复制private Map<Integer, PermissionCallback> permissionCallbacks = new HashMap<>();
public void requestPermissions(String[] permissions, PermissionCallback callback) {
int requestCode = generateRequestCode();
permissionCallbacks.put(requestCode, callback);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
requestPermissions(permissions, requestCode);
}
}
@Override
public void onRequestPermissionsResult(...) {
PermissionCallback callback = permissionCallbacks.get(requestCode);
if (callback != null) {
callback.onResult(grantResults);
permissionCallbacks.remove(requestCode);
}
}
使用示例:
java复制requestPermissions(
new String[]{Manifest.permission.CAMERA},
granted -> {
if (granted) openCamera();
else showPermissionTips();
}
);
3.2 页面跳转封装
java复制public void startActivity(Class<?> clazz, Bundle extras, int enterAnim, int exitAnim) {
Intent intent = new Intent(this, clazz);
if (extras != null) intent.putExtras(extras);
startActivity(intent);
overridePendingTransition(enterAnim, exitAnim);
}
配套的动画资源建议:
- 右进左出(常规跳转)
- 下进上出(底部弹窗)
- 淡入淡出(全屏弹窗)
4. 性能优化要点
4.1 内存泄漏防护
java复制private List<Disposable> disposables = new ArrayList<>();
protected void autoDispose(Disposable disposable) {
disposables.add(disposable);
}
@Override
protected void onDestroy() {
for (Disposable d : disposables) {
if (d != null && !d.isDisposed()) {
d.dispose();
}
}
super.onDestroy();
}
4.2 视图绑定优化
传统findViewById的替代方案:
java复制protected <T extends View> T bindView(@IdRes int id) {
return findViewById(id);
}
// 使用示例
TextView titleView = bindView(R.id.tv_title);
更推荐使用ViewBinding:
java复制protected abstract VB getViewBinding();
@Override
protected void onCreate(...) {
super.onCreate(...);
VB binding = getViewBinding();
setContentView(binding.getRoot());
}
5. 实用扩展功能
5.1 状态栏适配方案
java复制protected void adaptStatusBar(boolean darkText) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
View decor = getWindow().getDecorView();
int flags = decor.getSystemUiVisibility();
if (darkText) {
flags |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
} else {
flags &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
}
decor.setSystemUiVisibility(flags);
}
}
5.2 键盘控制工具
java复制public void hideSoftInput() {
InputMethodManager imm = (InputMethodManager)
getSystemService(Context.INPUT_METHOD_SERVICE);
View focusView = getCurrentFocus();
if (focusView != null) {
imm.hideSoftInputFromWindow(
focusView.getWindowToken(),
InputMethodManager.HIDE_NOT_ALWAYS
);
}
}
6. 典型问题解决方案
6.1 多Fragment场景处理
常见问题:多个Fragment需要与Activity通信
解决方案:事件总线封装
java复制private final EventBus eventBus = new EventBus();
public void registerEventReceiver(Object receiver) {
if (!eventBus.isRegistered(receiver)) {
eventBus.register(receiver);
}
}
public void postEvent(Object event) {
eventBus.post(event);
}
6.2 横竖屏适配
配置建议:
xml复制<activity
android:name=".MainActivity"
android:configChanges="orientation|screenSize|keyboardHidden"
android:screenOrientation="portrait" />
代码控制:
java复制public void lockOrientation(boolean portrait) {
setRequestedOrientation(portrait
? ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
: ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
7. 最佳实践建议
-
功能模块化拆分:将不同功能拆分为独立Manager(如PermissionManager、UIManager)
-
合理使用组合模式:对于非必要功能,采用接口方式提供(避免继承层次过深)
-
版本兼容处理:
java复制protected void applyFullScreen() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
}
}
- 文档规范:为所有公共方法添加详细注释,说明使用场景和注意事项
实际项目中,这样的BaseActivity可以减少30%-50%的重复代码量,特别是对于包含20+个Activity的中大型项目效果尤为明显。建议根据项目特点选择性实现上述功能,避免过度设计。