如何将Android复杂页面组件化策略转化为?

摘要:常见方案对比 方案 适用场景 特点 include 布局 静态拆分,不需要复用 简单,布局复用 自定义 View UI+逻辑封装,可复用 封装度高 Fragment 动态加载,独立生命周期 灵活,但复杂 RecyclerV
常见方案对比 方案 适用场景 特点 include 布局 静态拆分,不需要复用 简单,布局复用 自定义 View UI+逻辑封装,可复用 封装度高 Fragment 动态加载,独立生命周期 灵活,但复杂 RecyclerView 列表,每行算一个组件 最常用 实际建议 复杂页面(如患者详情页) ├── 患者基本信息卡片 → include 或 自定义 CardView ├── 医嘱列表区域 → RecyclerView + Adapter ├── 执行记录区域 → RecyclerView + Adapter ├── 备注信息区域 → include └── 底部操作栏 → include 不是越拆越好: 2-3 个简单区域 → 直接写一个 XML 重复使用的区域 → 抽成 include 或自定义 View 需要独立管理生命周期 → Fragment 列表类型 → RecyclerView 多组件编码示例 示例场景:登录页拆分 LoginActivity ├── 顶部 Logo 区域(LogoView) ├── 账号输入区域(AccountInputView) ├── 验证码区域(CaptchaView) └── 登录按钮区域(LoginButtonView) 方案 A:include + ViewBinding(简单拆分) activity_login.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="16dp"> <!-- 顶部 Logo --> <include android:id="@+id/layout_logo" layout="@layout/layout_login_logo" /> <!-- 账号输入 --> <include android:id="@+id/layout_account" layout="@layout/layout_account_input" /> <!-- 验证码 --> <include android:id="@+id/layout_captcha" layout="@layout/layout_captcha" /> <!-- 登录按钮 --> <include android:id="@+id/layout_login_btn" layout="@layout/layout_login_button" /> </LinearLayout> LoginActivity.java public class LoginActivity extends BaseActivity<ActivityLoginBinding> { @Override protected void initView(Bundle savedInstanceState) { // 每个子布局都可以单独操作 binding.layoutLogo.setLogo(R.drawable.ic_logo); binding.layoutAccount.setHint("请输入账号"); binding.layoutCaptcha.setOnRefreshListener(() -> viewModel.loadCaptcha()); binding.layoutLoginBtn.setOnClickListener(() -> submitLogin()); } @Override protected void observeViewModel() { // 集中管理所有 LiveData viewModel.getCaptchaState().observe(this, resource -> { if (resource.isSuccess()) { binding.layoutCaptcha.setImage(resource.getData().imageBase64); } }); } } 方案 B:自定义 View(封装业务逻辑) 适合复杂且可复用的组件,比如验证码组件: CaptchaView.java(自定义组件) public class CaptchaView extends LinearLayout { private ActivityCaptchaBinding binding; private OnRefreshListener refreshListener; public CaptchaView(Context context) { super(context); init(); } private void init() { binding = ActivityCaptchaBinding.inflate(LayoutInflater.from(getContext()), this, true); binding.btnRefresh.setOnClickListener(v -> { if (refreshListener != null) refreshListener.onRefresh(); }); } /** 设置验证码图片 */ public void setCaptchaImage(String base64) { // Base64 → Bitmap → 设置图片 } /** 获取用户输入的验证码 */ public String getCaptchaCode() { return binding.etCaptcha.getText().toString().trim(); } /** 清空输入 */ public void clear() { binding.etCaptcha.setText(""); } /** 显示加载中 */ public void showLoading() { binding.progressBar.setVisibility(View.VISIBLE); } public void setOnRefreshListener(OnRefreshListener listener) { this.refreshListener = listener; } public interface OnRefreshListener { void onRefresh(); } } activity_login.xml(使用自定义组件) <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="16dp"> <!-- 直接使用自定义组件! --> <com.xx.xxxxx.widget.CaptchaView android:id="@+id/captchaView" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> LoginActivity.java(更简洁) public class LoginActivity extends BaseActivity<ActivityLoginBinding> { @Override protected void initView(Bundle savedInstanceState) { // 验证码组件的逻辑封装在 CaptchaView 内部 binding.captchaView.setOnRefreshListener(() -> viewModel.loadCaptcha()); } @Override protected void observeViewModel() { viewModel.getCaptchaState().observe(this, resource -> { if (resource.isSuccess()) { binding.captchaView.setCaptchaImage(resource.getData().imageBase64); } }); } private void submitLogin() { String captcha = binding.captchaView.getCaptchaCode(); // ... } } 方案 C:Fragment(动态拆分) 适合需要独立管理生命周期的场景: // PatientDetailActivity 使用多个 Fragment public class PatientDetailActivity extends BaseActivity { @Override protected void onCreate(Bundle savedInstanceState) { if (savedInstanceState == null) { // 动态添加 Fragment getSupportFragmentManager().beginTransaction() .add(R.id.container_info, new PatientInfoFragment()) .add(R.id.container_orders, new OrderListFragment()) .add(R.id.container_records, new RecordListFragment()) .commit(); } } } 总结 场景 应用 复杂页面拆分 重复用→抽组件不重复→直接写 多组件编码 简单用 include复杂用自定义 View动态加载用 Fragment 实际项目中: 登录页这种简单页面 → 直接写一个 XML + Activity 详情页 → include 抽公共部分 列表页 → RecyclerView + 多类型 ViewHolder Tab 切换 → Fragment