当前位置: 首页 > news >正文

Android架构模式推荐及分析和MVC架构模式制作一个简单的底部tab切换

目录

主流架构模式对比

适用场景

MVP‌:团队协作开发,需要高可测试性的项目

MVC架构模式制作一个简单的底部tab切换

(Model-View-Controller)结构

代码 

效果


主流架构模式对比

对比维度MVC‌ MVP‌ MVVM‌ MVI‌ 
学习曲线最低(基础分层清晰)中等(需接口抽象)较高(依赖数据绑定框架)最高(状态流管理复杂)
代码复杂度低(但易导致Controller臃肿)中等(分层明确)高(双向绑定调试难度大)极高(单向数据流逻辑严密)
可测试性差(业务与UI耦合)优秀(Presenter独立测试)良好(ViewModel可单元测试)优秀(状态隔离测试友好)
适用项目规模小型原型项目(<10个页面)中小型项目(10-50个页面)中大型项目(50+页面)高交互复杂项目(如金融交易)
使用率传统项目遗留较多(约25%)企业级应用常见(约35%)主流框架推荐(约40%)新兴趋势上升(约15%)
  • 小型简单项目‌:优先选择MVC,Android自带支持无需额外架构代码
  • 中型交互项目‌:MVVM通过数据绑定技术可减少约40%的UI同步代码
  • 测试驱动开发‌:MVP虽代码量较多但分层更清晰,便于单元测试

适用场景

  1. MVC‌:原生支持无需额外框架,推荐用于教学演示或超简易工具类App开发 
  2. MVP‌:团队协作开发,需要高可测试性的项目
  3. MVVM‌:响应式编程模式,适合长期维护的中大型项目(需搭配DataBinding或Jetpack Compose)
  4. MVI‌:适用于强状态管理需求(如实时聊天、股票交易系统)

MVC架构模式制作一个简单的底部tab切换

(Model-View-Controller)结构

src/
├── main/
│   ├── java/com/ys/autoapp/
│   │   ├── MainActivity.java        <-- Controller(主控制逻辑)
│   │   ├── HomeFragment.java        <-- Controller(首页页面逻辑)
│   │   ├── RulesFragment.java       <-- Controller(规则页面逻辑)
│   │   └── ProfileFragment.java     <-- Controller(我的页面逻辑)
│   │
│   ├── res/
│   │   ├── layout/
│   │   │   ├── activity_main.xml    <-- View(主界面布局)
│   │   │   ├── fragment_home.xml    <-- View(首页页面)
│   │   │   ├── fragment_rules.xml   <-- View(规则页面)
│   │   │   └── fragment_profile.xml <-- View(我的页面)
│   │   │
│   │   └── menu/
│   │       └── bottom_navigation_menu.xml <-- View(底部导航菜单定义)
│   │
│   └── drawable/
│       ├── ic_home.xml
│       ├── ic_rules.xml
│       └── ic_profile.xml           <-- View(图标资源)

代码 

MainActivity


import android.os.Bundle;
import android.util.Log;import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.navigation.NavigationBarView;public class MainActivity extends AppCompatActivity {private static final String TAG = "MainActivity";// 定义常量以替代资源 IDprivate static final int NAVIGATION_HOME = R.id.navigation_home;private static final int NAVIGATION_RULES = R.id.navigation_rules;private static final int NAVIGATION_PROFILE = R.id.navigation_profile;private FragmentManager fragmentManager;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);fragmentManager = getSupportFragmentManager();// 初始化底部导航栏BottomNavigationView bottomNavigationView = findViewById(R.id.bottom_navigation);bottomNavigationView.setOnItemSelectedListener(new NavigationBarView.OnItemSelectedListener() {@Overridepublic boolean onNavigationItemSelected(android.view.MenuItem item) {Log.d(TAG, "切换" + String.valueOf(item.getItemId()));Fragment selectedFragment = null;// 使用 if-else 替代 switch-case,避免变量重复赋值if (item.getItemId() == NAVIGATION_HOME) {selectedFragment = new HomeFragment();} else if (item.getItemId() == NAVIGATION_RULES) {selectedFragment = new RulesFragment();} else if (item.getItemId() == NAVIGATION_PROFILE) {selectedFragment = new ProfileFragment();}if (selectedFragment != null) {FragmentTransaction transaction = fragmentManager.beginTransaction();transaction.replace(R.id.fragment_container, selectedFragment);transaction.commit();}return true;}});// 默认显示首页bottomNavigationView.setSelectedItemId(NAVIGATION_HOME);}
}

HomeFragment

import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;public class HomeFragment extends Fragment {@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {return inflater.inflate(R.layout.fragment_home, container, false);}
}

ProfileFragment

import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;public class ProfileFragment extends Fragment {@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {return inflater.inflate(R.layout.fragment_profile, container, false);}
}

RulesFragment

import android.os.Bundle;
import androidx.fragment.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;public class RulesFragment extends Fragment {@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {return inflater.inflate(R.layout.fragment_rules, container, false);}
}

bottom_navigation_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"><itemandroid:id="@+id/navigation_home"android:icon="@drawable/ic_home"android:title="首页" /><itemandroid:id="@+id/navigation_rules"android:icon="@drawable/ic_rules"android:title="规则" /><itemandroid:id="@+id/navigation_profile"android:icon="@drawable/ic_profile"android:title="我的" />
</menu>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"><FrameLayoutandroid:id="@+id/fragment_container"android:layout_width="match_parent"android:layout_height="0dp"app:layout_constraintTop_toTopOf="parent"app:layout_constraintBottom_toTopOf="@id/bottom_navigation" /><com.google.android.material.bottomnavigation.BottomNavigationViewandroid:id="@+id/bottom_navigation"android:layout_width="match_parent"android:layout_height="wrap_content"app:layout_constraintBottom_toBottomOf="parent"app:menu="@menu/bottom_navigation_menu" /></androidx.constraintlayout.widget.ConstraintLayout>

fragment_home.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:gravity="center"android:background="#FFFFFF"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="首页"android:textSize="24sp"android:textColor="#000000" /><!-- 新增一行文本,标识当前页面 --><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="这是首页页面"android:textSize="16sp"android:textColor="#000000"android:layout_marginTop="16dp" /></LinearLayout>

fragment_rules.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:gravity="center"android:background="#FFFFFF"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="规则"android:textSize="24sp"android:textColor="#000000" /><!-- 新增一行文本,标识当前页面 --><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="这是规则页面"android:textSize="16sp"android:textColor="#000000"android:layout_marginTop="16dp" /></LinearLayout>

fragment_profile.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:gravity="center"android:background="#FFFFFF"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="我的"android:textSize="24sp"android:textColor="#000000" /><!-- 新增一行文本,标识当前页面 --><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="这是我的页面"android:textSize="16sp"android:textColor="#000000"android:layout_marginTop="16dp" /></LinearLayout>

ic_home.xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"android:width="24dp"android:height="24dp"android:viewportWidth="24"android:viewportHeight="24"><pathandroid:fillColor="#000000"android:pathData="M10 20v-6h4v6h5v-8h3L12 3 2 12h3v8z" />
</vector>

ic_rules.xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"android:width="24dp"android:height="24dp"android:viewportWidth="24"android:viewportHeight="24"><pathandroid:fillColor="#000000"android:pathData="M12 2L2 22h20L12 2z" />
</vector>

ic_profile.xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"android:width="24dp"android:height="24dp"android:viewportWidth="24"android:viewportHeight="24"><pathandroid:fillColor="#000000"android:pathData="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 3c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zm0 14.2c-2.5 0-4.71-0.98-6.29-2.58C4.59 15.72 4 13.55 4 11c0-1.66 0.59-3.22 1.57-4.42C5.16 6.21 6.42 5 8 5c1.58 0 3.04 1.21 3.92 2.59C11.96 6.78 13.22 5 14.8 5c1.58 0 3.04 1.21 3.92 2.59C19.41 7.78 20 9.34 20 11c0 2.55-0.59 4.72-1.57 6.22C17.71 19.02 15.5 20 12 20z" />
</vector>

效果

ending

人的一生 必须要学会做一件事 而且要做到透彻 才不枉此生...共勉 💪。

相关文章:

  • 【面板数据】省级农业及农村现代化指标数据(2011-2022年)
  • 架构进阶:74页数据架构设计总体规划方案【附全文阅读】
  • FastAPI实现JWT校验的完整指南
  • 前端浏览器判断设备类型的方法
  • Babel 深度解析:现代 JavaScript 开发的桥梁
  • LangChain 使用指南与原理
  • 滑动窗口:穿越数据的时光机
  • TypeScript 中的泛型工具详解
  • AI文字识别工具汇总
  • 【Java学习日记36】:javabeen学生系统
  • [思维模式-28]:《本质思考力》-8- 两种相反的构建与解构系统的思维模式:①自顶向下的分解、牵引;②自底向上的堆叠、聚合
  • 将PyQt5设计的程序打包成.exe文件
  • C35-数组和函数开发初见
  • DEEPPOLAR:通过深度学习发明非线性大核极坐标码(2)
  • 从3秒到500ms:一套完整的慢SQL分析与优化的经验
  • 英语听力口语词汇--2.宣传类
  • AVL树解析
  • NPDP.新产品开发职业认证知识体系NPDP.BOK
  • 抽奖系统-基本-注册
  • 元数据和主数据
  • 93岁南开退休教授陈生玺逝世,代表作《明清易代史独见》多次再版
  • 退休10年后,70岁成都高新区管委会原巡视员王晋成被查
  • 浙江公开征集涉企行政执法问题线索,包括乱收费、乱罚款等
  • “应急侠”上线,应急管理部正式发布应急科普IP形象
  • 学习时报头版:世界要公道不要霸道
  • 4月国产新能源,降价潮迈入拐点