Skip to content

Code Examples

This page contains all demo code from the tutorial, organized by module for easy reference and copying.

📁 Code Structure

code-examples/
├── 02-java-basics/              # Java Basics
│   ├── OopExample.java          # OOP: inheritance, interfaces, abstract classes
│   ├── CollectionsExample.java  # Collections: List, Map, Set, generics
│   └── DesignPatterns.java      # Design patterns: Singleton, Observer, Builder, Adapter
├── 04-activity-fragment/        # Activity & Fragment
│   ├── LifecycleActivity.java   # Activity lifecycle demo
│   └── DetailActivity.java      # Data passing between pages
├── 05-ui-layouts/               # UI Layouts
│   └── profile_layout.xml       # ConstraintLayout profile page
├── 06-recyclerview/             # RecyclerView
│   └── UserListAdapter.java     # ListAdapter + DiffUtil example
├── 07-networking-persistence/   # Networking & Storage
│   └── ApiExample.java          # Retrofit complete example
├── 08-architecture/             # Architecture Patterns
│   └── MVVMExample.java         # Complete MVVM architecture
└── 10-legacy-migration/         # Legacy Migration
    └── BeforeMigration.java     # Java → Kotlin comparison

🚀 How to Use

  1. Click on the corresponding module to view the code
  2. Copy the code into your Android Studio project
  3. Understand the logic through comments
  4. Modify and experiment on your own

📝 Code Conventions

  • All examples are based on JDK 17 and compileSdk 34
  • Uses AndroidX libraries instead of Support Library
  • Follows modern Android development best practices
  • Includes detailed bilingual comments

📖 Code Preview

Java Basics: Object-Oriented Programming

java
package com.example.basics;

import java.util.ArrayList;
import java.util.List;

/**
 * 面向对象示例:对比前端原型链和 Java 类继承
 *
 * 前端类比:
 * - class = ES6 class
 * - extends = extends
 * - interface = TypeScript interface
 * - abstract class = 无直接对应,类似抽象基类
 */
public class OopExample {

    // ==================== 基础类定义 ====================

    /**
     * 基类:动物
     * 前端类比:class Animal { constructor(name) { this.name = name; } }
     */
    static class Animal {
        private String name;
        private int age;

        // 构造方法(前端类比:constructor)
        public Animal(String name, int age) {
            this.name = name;
            this.age = age;
        }

        // Getter/Setter(前端类比:get name() / set name())
        public String getName() { return name; }
        public void setName(String name) { this.name = name; }
        public int getAge() { return age; }
        public void setAge(int age) { this.age = age; }

        // 可重写的方法
        public String makeSound() {
            return "...";
        }

        @Override
        public String toString() {
            return name + " (" + age + "岁)";
        }
    }

    /**
     * 继承:狗
     * 前端类比:class Dog extends Animal { makeSound() { return '汪!'; } }
     */
    static class Dog extends Animal {
        private String breed;

        public Dog(String name, int age, String breed) {
            super(name, age);  // 调用父类构造方法(前端:super(name, age))
            this.breed = breed;
        }

        @Override
        public String makeSound() {
            return "汪汪!";
        }

        public String getBreed() { return breed; }
    }

    /**
     * 继承:猫
     */
    static class Cat extends Animal {
        private boolean isIndoor;

        public Cat(String name, int age, boolean isIndoor) {
            super(name, age);
            this.isIndoor = isIndoor;
        }

        @Override
        public String makeSound() {
            return "喵喵~";
        }

        public boolean isIndoor() { return isIndoor; }
    }

    // ==================== 接口示例 ====================

    /**
     * 接口:可训练的
     * 前端类比:interface Trainable { train(command: string): void; }
     */
    interface Trainable {
        void train(String command);
        boolean canPerform(String trick);
    }

    /**
     * 接口:可抚摸的
     */
    interface Pettable {
        void pet();
        String getReaction();
    }

    /**
     * 多接口实现:导盲犬
     * 前端类比:class GuideDog extends Dog implements Trainable, Pettable
     */
    static class GuideDog extends Dog implements Trainable, Pettable {
        private List<String> knownTricks = new ArrayList<>();

        public GuideDog(String name, int age, String breed) {
            super(name, age, breed);
        }

        @Override
        public void train(String command) {
            knownTricks.add(command);
            System.out.println(getName() + " 学会了: " + command);
        }

        @Override
        public boolean canPerform(String trick) {
            return knownTricks.contains(trick);
        }

        @Override
        public void pet() {
            System.out.println(getName() + " 摇尾巴");
        }

        @Override
        public String getReaction() {
            return "友好地蹭你的手";
        }
    }

    // ==================== 抽象类示例 ====================

    /**
     * 抽象类:形状
     * 前端类比:abstract class Shape { abstract area(): number; }
     */
    static abstract class Shape {
        protected String color;

        public Shape(String color) {
            this.color = color;
        }

        // 抽象方法(必须在子类中实现)
        public abstract double area();
        public abstract double perimeter();

        // 具体方法
        public void describe() {
            System.out.println(color + " 形状,面积: " + area() + ",周长: " + perimeter());
        }
    }

    static class Circle extends Shape {
        private double radius;

        public Circle(String color, double radius) {
            super(color);
            this.radius = radius;
        }

        @Override
        public double area() {
            return Math.PI * radius * radius;
        }

        @Override
        public double perimeter() {
            return 2 * Math.PI * radius;
        }
    }

    static class Rectangle extends Shape {
        private double width, height;

        public Rectangle(String color, double width, double height) {
            super(color);
            this.width = width;
            this.height = height;
        }

        @Override
        public double area() {
            return width * height;
        }

        @Override
        public double perimeter() {
            return 2 * (width + height);
        }
    }

    // ==================== 演示入口 ====================

    public static void main(String[] args) {
        System.out.println("=== 继承与多态 ===");

        Animal dog = new Dog("旺财", 3, "金毛");
        Animal cat = new Cat("咪咪", 2, true);

        System.out.println(dog);  // 旺财 (3岁)
        System.out.println(cat);  // 咪咪 (2岁)
        System.out.println(dog.makeSound());  // 汪汪!
        System.out.println(cat.makeSound());  // 喵喵~

        System.out.println("\n=== 接口实现 ===");

        GuideDog guideDog = new GuideDog("Lucky", 4, "拉布拉多");
        guideDog.train("带路");
        guideDog.train("停下");
        guideDog.pet();

        System.out.println("会带路吗?" + guideDog.canPerform("带路"));  // true
        System.out.println("会翻滚吗?" + guideDog.canPerform("翻滚"));  // false

        System.out.println("\n=== 抽象类 ===");

        Shape circle = new Circle("红色", 5);
        Shape rect = new Rectangle("蓝色", 4, 6);

        circle.describe();
        rect.describe();

        System.out.println("\n=== 类型检查(前端:instanceof) ===");
        System.out.println("dog instanceof Animal: " + (dog instanceof Animal));  // true
        System.out.println("dog instanceof Dog: " + (dog instanceof Dog));  // true
        System.out.println("dog instanceof Cat: " + (dog instanceof Cat));  // false
        System.out.println("guideDog instanceof Trainable: " + (guideDog instanceof Trainable));  // true
    }
}

Collections Framework

java
package com.example.basics;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 集合框架示例:对比前端数组/对象操作
 *
 * 前端类比:
 * - List<T> = Array<T>
 * - Map<K,V> = Map<K,V> / Record<K,V>
 * - Set<T> = Set<T>
 * - Iterator = for...of
 */
public class CollectionsExample {

    // ==================== List 示例 ====================

    /**
     * List 操作对比
     *
     * | Java | JavaScript |
     * |------|-----------|
     * | list.add(item) | arr.push(item) |
     * | list.get(i) | arr[i] |
     * | list.remove(i) | arr.splice(i, 1) |
     * | list.size() | arr.length |
     * | list.contains(x) | arr.includes(x) |
     */
    static void listExamples() {
        System.out.println("=== List 示例 ===");

        // ArrayList(最常用,类似 JS 数组)
        List<String> fruits = new ArrayList<>();
        fruits.add("苹果");
        fruits.add("香蕉");
        fruits.add("橙子");

        System.out.println("水果列表: " + fruits);
        System.out.println("第一个: " + fruits.get(0));  // 苹果
        System.out.println("包含香蕉? " + fruits.contains("香蕉"));  // true

        // 遍历(前端:fruits.forEach(f => ...))
        System.out.println("\n遍历:");
        for (String fruit : fruits) {
            System.out.println("  - " + fruit);
        }

        // Lambda 遍历(前端:fruits.forEach(f => console.log(f)))
        System.out.println("\nLambda 遍历:");
        fruits.forEach(fruit -> System.out.println("  * " + fruit));

        // Stream API(前端:arr.filter/map/reduce)
        List<String> longNames = fruits.stream()
                .filter(f -> f.length() >= 2)
                .collect(Collectors.toList());
        System.out.println("名字>=2字符: " + longNames);

        // 映射(前端:arr.map)
        List<Integer> lengths = fruits.stream()
                .map(String::length)
                .collect(Collectors.toList());
        System.out.println("名字长度: " + lengths);

        // 排序(前端:arr.sort)
        fruits.sort(Comparator.naturalOrder());
        System.out.println("排序后: " + fruits);
    }

    // ==================== Map 示例 ====================

    /**
     * Map 操作对比
     *
     * | Java | JavaScript |
     * |------|-----------|
     * | map.put(k, v) | map.set(k, v) / obj[k] = v |
     * | map.get(k) | map.get(k) / obj[k] |
     * | map.containsKey(k) | map.has(k) / k in obj |
     * | map.keySet() | map.keys() / Object.keys(obj) |
     */
    static void mapExamples() {
        System.out.println("\n=== Map 示例 ===");

        // HashMap(无序,类似 JS Map 或对象)
        Map<String, Integer> scores = new HashMap<>();
        scores.put("张三", 95);
        scores.put("李四", 87);
        scores.put("王五", 92);

        System.out.println("成绩表: " + scores);
        System.out.println("张三成绩: " + scores.get("张三"));  // 95
        System.out.println("包含李四? " + scores.containsKey("李四"));  // true

        // 遍历(前端:for (const [k, v] of map))
        System.out.println("\n遍历:");
        for (Map.Entry<String, Integer> entry : scores.entrySet()) {
            System.out.println("  " + entry.getKey() + ": " + entry.getValue());
        }

        // Lambda 遍历
        System.out.println("\nLambda 遍历:");
        scores.forEach((name, score) ->
            System.out.println("  " + name + " -> " + score)
        );

        // getOrDefault(前端:obj[k] ?? defaultValue)
        System.out.println("赵六成绩: " + scores.getOrDefault("赵六", 0));  // 0

        // TreeMap(有序 Map)
        Map<String, Integer> sortedScores = new TreeMap<>(scores);
        System.out.println("按姓名排序: " + sortedScores);
    }

    // ==================== Set 示例 ====================

    /**
     * Set 操作对比
     *
     * | Java | JavaScript |
     * |------|-----------|
     * | set.add(x) | set.add(x) |
     * | set.contains(x) | set.has(x) |
     * | set.remove(x) | set.delete(x) |
     * | set.size() | set.size |
     */
    static void setExamples() {
        System.out.println("\n=== Set 示例 ===");

        Set<String> tags = new HashSet<>();
        tags.add("Android");
        tags.add("Java");
        tags.add("Kotlin");
        tags.add("Android");  // 重复,不会添加

        System.out.println("标签集合: " + tags);
        System.out.println("包含 Java? " + tags.contains("Java"));  // true
        System.out.println("集合大小: " + tags.size());  // 3

        // 集合运算
        Set<String> myTags = new HashSet<>(Arrays.asList("Java", "Web", "Android"));
        Set<String> yourTags = new HashSet<>(Arrays.asList("Kotlin", "Android", "iOS"));

        // 交集(前端:new Set([...a].filter(x => b.has(x))))
        Set<String> intersection = new HashSet<>(myTags);
        intersection.retainAll(yourTags);
        System.out.println("交集: " + intersection);  // [Android]

        // 并集(前端:new Set([...a, ...b]))
        Set<String> union = new HashSet<>(myTags);
        union.addAll(yourTags);
        System.out.println("并集: " + union);  // [Java, Web, Android, Kotlin, iOS]

        // 差集
        Set<String> difference = new HashSet<>(myTags);
        difference.removeAll(yourTags);
        System.out.println("差集 (my - your): " + difference);  // [Java, Web]
    }

    // ==================== 泛型示例 ====================

    /**
     * 泛型类(前端类比:class Stack<T>)
     */
    static class Stack<T> {
        private List<T> items = new ArrayList<>();

        public void push(T item) {
            items.add(item);
        }

        public T pop() {
            if (items.isEmpty()) throw new RuntimeException("栈为空");
            return items.remove(items.size() - 1);
        }

        public T peek() {
            if (items.isEmpty()) throw new RuntimeException("栈为空");
            return items.get(items.size() - 1);
        }

        public boolean isEmpty() {
            return items.isEmpty();
        }

        public int size() {
            return items.size();
        }
    }

    /**
     * 泛型方法
     */
    static <T extends Comparable<T>> T findMax(List<T> list) {
        if (list.isEmpty()) throw new IllegalArgumentException("列表为空");
        T max = list.get(0);
        for (T item : list) {
            if (item.compareTo(max) > 0) {
                max = item;
            }
        }
        return max;
    }

    static void genericsExamples() {
        System.out.println("\n=== 泛型示例 ===");

        // 泛型类
        Stack<String> stack = new Stack<>();
        stack.push("A");
        stack.push("B");
        stack.push("C");

        System.out.println("栈顶: " + stack.peek());  // C
        System.out.println("弹出: " + stack.pop());   // C
        System.out.println("栈顶: " + stack.peek());  // B

        // 泛型方法
        List<Integer> numbers = Arrays.asList(3, 7, 1, 9, 4);
        System.out.println("最大值: " + findMax(numbers));  // 9

        List<String> words = Arrays.asList("banana", "apple", "cherry");
        System.out.println("最大字符串: " + findMax(words));  // cherry
    }

    // ==================== 主方法 ====================

    public static void main(String[] args) {
        listExamples();
        mapExamples();
        setExamples();
        genericsExamples();
    }
}

Design Patterns

java
package com.example.basics;

/**
 * 设计模式示例:Android 开发中常用的模式
 *
 * 包含:
 * - 单例模式 (Singleton)
 * - 观察者模式 (Observer)
 * - 构建者模式 (Builder)
 * - 适配器模式 (Adapter)
 */
public class DesignPatterns {

    // ==================== 单例模式 ====================

    /**
     * 单例模式:确保一个类只有一个实例
     *
     * 前端类比:Redux Store、全局状态管理
     * Android 场景:数据库实例、网络客户端、配置管理
     */
    static class DatabaseHelper {
        // 静态实例(前端:module 级别的变量)
        private static DatabaseHelper instance;

        private String connectionString;
        private boolean isConnected;

        // 私有构造方法(前端:私有 constructor 或工厂函数)
        private DatabaseHelper() {
            this.connectionString = "jdbc:sqlite:app.db";
            this.isConnected = false;
        }

        // 获取实例(线程安全)
        public static synchronized DatabaseHelper getInstance() {
            if (instance == null) {
                instance = new DatabaseHelper();
            }
            return instance;
        }

        public void connect() {
            isConnected = true;
            System.out.println("数据库已连接: " + connectionString);
        }

        public void disconnect() {
            isConnected = false;
            System.out.println("数据库已断开");
        }

        public boolean isConnected() {
            return isConnected;
        }
    }

    // ==================== 观察者模式 ====================

    /**
     * 观察者接口(前端:EventListener / Subscriber)
     */
    interface Observer<T> {
        void update(T data);
    }

    /**
     * 被观察者(前端:EventEmitter / Subject)
     * Android 场景:LiveData、EventBus
     */
    static class LiveData<T> {
        private T value;
        private List<Observer<T>> observers = new java.util.ArrayList<>();

        public void observe(Observer<T> observer) {
            observers.add(observer);
        }

        public void removeObserver(Observer<T> observer) {
            observers.remove(observer);
        }

        public void setValue(T newValue) {
            this.value = newValue;
            notifyObservers();
        }

        public T getValue() {
            return value;
        }

        private void notifyObservers() {
            for (Observer<T> observer : observers) {
                observer.update(value);
            }
        }
    }

    /**
     * 用户状态示例
     */
    static class UserState {
        public String name;
        public boolean isLoggedIn;

        public UserState(String name, boolean isLoggedIn) {
            this.name = name;
            this.isLoggedIn = isLoggedIn;
        }

        @Override
        public String toString() {
            return name + (isLoggedIn ? " (在线)" : " (离线)");
        }
    }

    // ==================== 构建者模式 ====================

    /**
     * 构建者模式:复杂对象的分步构建
     *
     * 前端类比:链式调用、配置对象构建
     * Android 场景:Dialog、Request、Notification
     */
    static class HttpRequest {
        private final String url;
        private final String method;
        private final Map<String, String> headers;
        private final String body;
        private final int timeout;

        // 私有构造方法,只能通过 Builder 创建
        private HttpRequest(Builder builder) {
            this.url = builder.url;
            this.method = builder.method;
            this.headers = builder.headers;
            this.body = builder.body;
            this.timeout = builder.timeout;
        }

        @Override
        public String toString() {
            return method + " " + url + "\n" +
                   "Headers: " + headers + "\n" +
                   "Body: " + (body != null ? body : "(无)") + "\n" +
                   "Timeout: " + timeout + "ms";
        }

        /**
         * Builder 类(前端:链式调用 new Request().url().method().build())
         */
        public static class Builder {
            private String url;
            private String method = "GET";
            private Map<String, String> headers = new java.util.HashMap<>();
            private String body;
            private int timeout = 30000;

            public Builder(String url) {
                this.url = url;
            }

            public Builder method(String method) {
                this.method = method;
                return this;  // 返回 this 实现链式调用
            }

            public Builder header(String key, String value) {
                this.headers.put(key, value);
                return this;
            }

            public Builder body(String body) {
                this.body = body;
                return this;
            }

            public Builder timeout(int timeout) {
                this.timeout = timeout;
                return this;
            }

            public HttpRequest build() {
                return new HttpRequest(this);
            }
        }
    }

    // ==================== 适配器模式 ====================

    /**
     * 适配器模式:接口转换
     *
     * 前端类比:数据转换层、API 适配
     * Android 场景:RecyclerView.Adapter
     */

    // 旧接口
    interface OldDataSource {
        String[] getRawData();
    }

    // 新接口
    interface NewDataSource {
        List<User> getUsers();
    }

    static class User {
        public String name;
        public int age;

        public User(String name, int age) {
            this.name = name;
            this.age = age;
        }

        @Override
        public String toString() {
            return name + " (" + age + ")";
        }
    }

    // 旧实现
    static class LegacyDataSource implements OldDataSource {
        @Override
        public String[] getRawData() {
            return new String[]{"张三|25", "李四|30", "王五|28"};
        }
    }

    // 适配器:将旧接口转换为新接口
    static class DataSourceAdapter implements NewDataSource {
        private OldDataSource oldSource;

        public DataSourceAdapter(OldDataSource oldSource) {
            this.oldSource = oldSource;
        }

        @Override
        public List<User> getUsers() {
            List<User> users = new java.util.ArrayList<>();
            String[] rawData = oldSource.getRawData();

            for (String item : rawData) {
                String[] parts = item.split("\\|");
                users.add(new User(parts[0], Integer.parseInt(parts[1])));
            }

            return users;
        }
    }

    // ==================== 演示入口 ====================

    public static void main(String[] args) {
        System.out.println("=== 单例模式 ===");
        DatabaseHelper db1 = DatabaseHelper.getInstance();
        DatabaseHelper db2 = DatabaseHelper.getInstance();
        System.out.println("db1 == db2: " + (db1 == db2));  // true
        db1.connect();
        System.out.println("db2 连接状态: " + db2.isConnected());  // true

        System.out.println("\n=== 观察者模式 ===");
        LiveData<UserState> userState = new LiveData<>();

        userState.observe(state -> System.out.println("UI 更新: " + state));
        userState.observe(state -> System.out.println("日志记录: " + state));

        userState.setValue(new UserState("张三", true));
        userState.setValue(new UserState("张三", false));

        System.out.println("\n=== 构建者模式 ===");
        HttpRequest request = new HttpRequest.Builder("https://api.example.com/users")
                .method("POST")
                .header("Content-Type", "application/json")
                .header("Authorization", "Bearer token123")
                .body("{\"name\": \"张三\", \"age\": 25}")
                .timeout(10000)
                .build();
        System.out.println(request);

        System.out.println("\n=== 适配器模式 ===");
        OldDataSource oldSource = new LegacyDataSource();
        NewDataSource adapter = new DataSourceAdapter(oldSource);

        System.out.println("原始数据: " + java.util.Arrays.toString(oldSource.getRawData()));
        System.out.println("适配后: " + adapter.getUsers());
    }
}

Activity Lifecycle

java
package com.example.activity;

import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;

/**
 * Activity 生命周期演示
 *
 * 前端类比:
 * - onCreate() = 页面初始化(DOMContentLoaded)
 * - onStart() = 页面可见
 * - onResume() = 页面获得焦点
 * - onPause() = 页面失去焦点
 * - onStop() = 页面不可见
 * - onDestroy() = 页面销毁(beforeunload)
 *
 * 运行此 Activity 并在 Logcat 中观察生命周期日志输出。
 */
public class LifecycleActivity extends AppCompatActivity {

    private static final String TAG = "LifecycleActivity";
    private TextView lifecycleText;
    private int resumeCount = 0;

    /**
     * Activity 被创建时调用
     * 前端类比:componentDidMount / onMounted
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "onCreate: Activity 被创建");

        // 设置布局(前端类比:innerHTML = template)
        // 这里用代码创建 UI,实际项目中应该用 XML 布局
        lifecycleText = new TextView(this);
        lifecycleText.setTextSize(20);
        lifecycleText.setPadding(32, 32, 32, 32);

        Button navigateButton = new Button(this);
        navigateButton.setText("打开 DetailActivity");
        navigateButton.setOnClickListener(v -> {
            // 显式 Intent(前端类比:router.push('/detail'))
            Intent intent = new Intent(this, DetailActivity.class);
            intent.putExtra("title", "从 LifecycleActivity 传递的标题");
            intent.putExtra("id", 42);
            startActivity(intent);
        });

        Button backButton = new Button(this);
        backButton.setText("返回");
        backButton.setOnClickListener(v -> finish());  // 关闭当前 Activity

        android.widget.LinearLayout layout = new android.widget.LinearLayout(this);
        layout.setOrientation(android.widget.LinearLayout.VERTICAL);
        layout.addView(lifecycleText);
        layout.addView(navigateButton);
        layout.addView(backButton);

        setContentView(layout);

        // 恢复状态(前端类比:从 sessionStorage 恢复)
        if (savedInstanceState != null) {
            resumeCount = savedInstanceState.getInt("resumeCount", 0);
            Log.d(TAG, "onCreate: 从 savedInstanceState 恢复状态");
        }

        lifecycleText.setText("LifecycleActivity\nonCreate 调用\nResume 次数: " + resumeCount);
    }

    /**
     * Activity 变为可见时调用
     */
    @Override
    protected void onStart() {
        super.onStart();
        Log.d(TAG, "onStart: Activity 变为可见");
    }

    /**
     * Activity 获得焦点,进入前台时调用
     * 前端类比:window focus 事件
     */
    @Override
    protected void onResume() {
        super.onResume();
        resumeCount++;
        Log.d(TAG, "onResume: Activity 进入前台 (第 " + resumeCount + " 次)");
        lifecycleText.setText("LifecycleActivity\nonResume 调用\nResume 次数: " + resumeCount);
    }

    /**
     * Activity 失去焦点时调用
     * 前端类比:window blur 事件
     */
    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG, "onPause: Activity 失去焦点");
    }

    /**
     * Activity 变为不可见时调用
     */
    @Override
    protected void onStop() {
        super.onStop();
        Log.d(TAG, "onStop: Activity 变为不可见");
    }

    /**
     * Activity 被销毁时调用
     * 前端类比:componentWillUnmount / onUnmounted
     */
    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy: Activity 被销毁");
    }

    /**
     * 保存状态(系统可能杀死进程时)
     * 前端类比:beforeunload 时保存到 sessionStorage
     */
    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putInt("resumeCount", resumeCount);
        Log.d(TAG, "onSaveInstanceState: 保存 resumeCount = " + resumeCount);
    }

    /**
     * 从后台返回前台时调用(在 onStart 之前)
     */
    @Override
    protected void onRestart() {
        super.onRestart();
        Log.d(TAG, "onRestart: Activity 从后台返回");
    }
}

Data Passing Between Pages

java
package com.example.activity;

import android.content.Intent;
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;

/**
 * DetailActivity:演示页面间数据传递
 *
 * 前端类比:
 * - Intent extras = route params / query params
 * - setResult() + finish() = emit event + go back
 * - startActivityForResult() = 弹窗回调
 */
public class DetailActivity extends AppCompatActivity {

    private static final String TAG = "DetailActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // 接收 Intent 数据(前端类比:this.$route.params)
        Intent intent = getIntent();
        String title = intent.getStringExtra("title");
        int id = intent.getIntExtra("id", -1);

        android.util.Log.d(TAG, "接收到数据: title=" + title + ", id=" + id);

        // 创建 UI
        TextView titleView = new TextView(this);
        titleView.setTextSize(24);
        titleView.setPadding(32, 32, 32, 32);
        titleView.setText("详情页面\n\n标题: " + title + "\nID: " + id);

        Button backButton = new Button(this);
        backButton.setText("返回");
        backButton.setOnClickListener(v -> {
            // 返回结果给调用方(前端类比:emit('close', result))
            Intent result = new Intent();
            result.putExtra("result", "操作完成");
            setResult(RESULT_OK, result);
            finish();  // 关闭当前 Activity
        });

        Button shareButton = new Button(this);
        shareButton.setText("分享(隐式 Intent)");
        shareButton.setOnClickListener(v -> {
            // 隐式 Intent(前端类比:window.open 或调用系统分享)
            Intent shareIntent = new Intent(Intent.ACTION_SEND);
            shareIntent.setType("text/plain");
            shareIntent.putExtra(Intent.EXTRA_TEXT, "查看: " + title);
            startActivity(Intent.createChooser(shareIntent, "分享到"));
        });

        android.widget.LinearLayout layout = new android.widget.LinearLayout(this);
        layout.setOrientation(android.widget.LinearLayout.VERTICAL);
        layout.addView(titleView);
        layout.addView(backButton);
        layout.addView(shareButton);

        setContentView(layout);
    }
}

UI Layout: ConstraintLayout

xml
<?xml version="1.0" encoding="utf-8"?>
<!--
    ConstraintLayout 示例:现代 Android 布局

    前端类比:
    - ConstraintLayout = CSS Flexbox + Grid
    - layout_constraintX_toXOf = flex/grid 对齐
    - layout_margin = margin
    - layout_padding = padding

    依赖:implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
-->
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp">

    <!-- 头像(圆形) -->
    <ImageView
        android:id="@+id/avatar"
        android:layout_width="80dp"
        android:layout_height="80dp"
        android:src="@drawable/ic_person"
        android:background="@drawable/circle_background"
        android:scaleType="centerCrop"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        tools:ignore="ContentDescription" />

    <!-- 用户名 -->
    <TextView
        android:id="@+id/username"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="张三"
        android:textSize="24sp"
        android:textStyle="bold"
        android:textColor="#333333"
        android:layout_marginStart="16dp"
        app:layout_constraintTop_toTopOf="@id/avatar"
        app:layout_constraintStart_toEndOf="@id/avatar"
        app:layout_constraintEnd_toEndOf="parent"
        tools:text="用户名" />

    <!-- 邮箱 -->
    <TextView
        android:id="@+id/email"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="zhangsan@example.com"
        android:textSize="14sp"
        android:textColor="#666666"
        android:layout_marginTop="4dp"
        app:layout_constraintTop_toBottomOf="@id/username"
        app:layout_constraintStart_toStartOf="@id/username"
        app:layout_constraintEnd_toEndOf="@id/username"
        tools:text="email@example.com" />

    <!-- 分隔线 -->
    <View
        android:id="@+id/divider"
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#E0E0E0"
        android:layout_marginTop="16dp"
        app:layout_constraintTop_toBottomOf="@id/avatar" />

    <!-- 统计信息区域 -->
    <LinearLayout
        android:id="@+id/stats_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_marginTop="16dp"
        app:layout_constraintTop_toBottomOf="@id/divider">

        <!-- 粉丝数 -->
        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:orientation="vertical"
            android:gravity="center">

            <TextView
                android:id="@+id/followers_count"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="1.2K"
                android:textSize="20sp"
                android:textStyle="bold"
                android:textColor="#333333" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="粉丝"
                android:textSize="12sp"
                android:textColor="#999999" />
        </LinearLayout>

        <!-- 关注数 -->
        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:orientation="vertical"
            android:gravity="center">

            <TextView
                android:id="@+id/following_count"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="256"
                android:textSize="20sp"
                android:textStyle="bold"
                android:textColor="#333333" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="关注"
                android:textSize="12sp"
                android:textColor="#999999" />
        </LinearLayout>

        <!-- 获赞数 -->
        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:orientation="vertical"
            android:gravity="center">

            <TextView
                android:id="@+id/likes_count"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="5.8K"
                android:textSize="20sp"
                android:textStyle="bold"
                android:textColor="#333333" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="获赞"
                android:textSize="12sp"
                android:textColor="#999999" />
        </LinearLayout>
    </LinearLayout>

    <!-- 关注按钮 -->
    <Button
        android:id="@+id/follow_button"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="关注"
        android:textSize="16sp"
        android:layout_marginTop="24dp"
        app:layout_constraintTop_toBottomOf="@id/stats_container"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toStartOf="@id/message_button"
        android:layout_marginEnd="8dp" />

    <!-- 私信按钮 -->
    <Button
        android:id="@+id/message_button"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="私信"
        android:textSize="16sp"
        android:backgroundTint="#E0E0E0"
        android:textColor="#333333"
        app:layout_constraintTop_toTopOf="@id/follow_button"
        app:layout_constraintStart_toEndOf="@id/follow_button"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginStart="8dp" />

    <!-- 个人简介 -->
    <TextView
        android:id="@+id/bio_label"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="个人简介"
        android:textSize="16sp"
        android:textStyle="bold"
        android:textColor="#333333"
        android:layout_marginTop="24dp"
        app:layout_constraintTop_toBottomOf="@id/follow_button"
        app:layout_constraintStart_toStartOf="parent" />

    <TextView
        android:id="@+id/bio_text"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Android 开发者,热爱开源,专注于移动端架构设计。"
        android:textSize="14sp"
        android:textColor="#666666"
        android:lineSpacingExtra="4dp"
        android:layout_marginTop="8dp"
        app:layout_constraintTop_toBottomOf="@id/bio_label" />

</androidx.constraintlayout.widget.ConstraintLayout>

RecyclerView: ListAdapter + DiffUtil

java
package com.example.recyclerview;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.ListAdapter;
import androidx.recyclerview.widget.RecyclerView;

/**
 * RecyclerView Adapter 示例:使用 ListAdapter + DiffUtil
 *
 * 前端类比:
 * - Adapter = Vue 的 v-for / React 的 .map()
 * - ViewHolder = 列表项组件
 * - DiffUtil = Vue 的 key 属性 / React 的 key prop
 *
 * ListAdapter 比传统 RecyclerView.Adapter 更高效:
 * - 自动计算差异(DiffUtil)
 * - 只更新变化的项
 * - 动画效果更流畅
 */
public class UserListAdapter extends ListAdapter<User, UserListAdapter.UserViewHolder> {

    private OnItemClickListener listener;

    /**
     * 点击事件接口(前端类比:@click / onClick)
     */
    public interface OnItemClickListener {
        void onItemClick(User user, int position);
        void onItemLongClick(User user, int position);
    }

    public UserListAdapter(OnItemClickListener listener) {
        super(DIFF_CALLBACK);
        this.listener = listener;
    }

    /**
     * DiffUtil 回调:告诉 RecyclerView 如何比较两个 item
     *
     * 前端类比:Vue 的 :key="user.id" 或 React 的 key={user.id}
     */
    private static final DiffUtil.ItemCallback<User> DIFF_CALLBACK =
            new DiffUtil.ItemCallback<User>() {
                /**
                 * 判断两个 item 是否是同一个(前端类比:id 是否相同)
                 */
                @Override
                public boolean areItemsTheSame(@NonNull User oldItem, @NonNull User newItem) {
                    return oldItem.getId() == newItem.getId();
                }

                /**
                 * 判断两个 item 内容是否相同(前端类比:deepEqual)
                 */
                @Override
                public boolean areContentsTheSame(@NonNull User oldItem, @NonNull User newItem) {
                    return oldItem.getName().equals(newItem.getName()) &&
                           oldItem.getEmail().equals(newItem.getEmail()) &&
                           oldItem.getRole().equals(newItem.getRole());
                }
            };

    /**
     * 创建 ViewHolder(前端类比:创建组件实例)
     *
     * 只在需要新 ViewHolder 时调用,不会为每个 item 都调用。
     * RecyclerView 会复用滑出屏幕的 ViewHolder。
     */
    @NonNull
    @Override
    public UserViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        // 加载布局(前端类比:读取 template)
        View view = LayoutInflater.from(parent.getContext())
                .inflate(android.R.layout.simple_list_item_2, parent, false);
        return new UserViewHolder(view);
    }

    /**
     * 绑定数据到 ViewHolder(前端类比:给组件传 props)
     *
     * 每次 item 显示时都会调用。
     */
    @Override
    public void onBindViewHolder(@NonNull UserViewHolder holder, int position) {
        User user = getItem(position);  // ListAdapter 提供的便捷方法
        holder.bind(user, position, listener);
    }

    /**
     * ViewHolder:持有列表项的视图引用
     *
     * 前端类比:列表项组件的实例
     * 作用:避免重复调用 findViewById(性能优化)
     */
    static class UserViewHolder extends RecyclerView.ViewHolder {
        private TextView text1;
        private TextView text2;

        public UserViewHolder(@NonNull View itemView) {
            super(itemView);
            // simple_list_item_2 包含两个 TextView
            text1 = itemView.findViewById(android.R.id.text1);
            text2 = itemView.findViewById(android.R.id.text2);
        }

        public void bind(User user, int position, OnItemClickListener listener) {
            text1.setText(user.getName() + " (" + user.getRole() + ")");
            text2.setText(user.getEmail());

            // 点击事件(前端类比:@click)
            itemView.setOnClickListener(v -> {
                if (listener != null) {
                    listener.onItemClick(user, position);
                }
            });

            // 长按事件(前端类比:@contextmenu)
            itemView.setOnLongClickListener(v -> {
                if (listener != null) {
                    listener.onItemLongClick(user, position);
                }
                return true;
            });
        }
    }

    /**
     * 用户数据类
     */
    public static class User {
        private int id;
        private String name;
        private String email;
        private String role;

        public User(int id, String name, String email, String role) {
            this.id = id;
            this.name = name;
            this.email = email;
            this.role = role;
        }

        public int getId() { return id; }
        public String getName() { return name; }
        public String getEmail() { return email; }
        public String getRole() { return role; }
    }
}

Networking: Retrofit

java
package com.example.networking;

import java.io.IOException;
import java.util.List;

import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.http.Body;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.Path;
import retrofit2.http.Query;

/**
 * Retrofit 网络请求示例
 *
 * 前端类比:
 * - Retrofit = axios / fetch
 * - @GET/@POST = method: 'GET'/'POST'
 * - @Path = 路径参数 (如 /users/:id)
 * - @Query = 查询参数 (?page=1)
 * - @Body = 请求体
 * - Call<T> = Promise<T>
 *
 * 依赖配置 (build.gradle):
 * implementation 'com.squareup.retrofit2:retrofit:2.9.0'
 * implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
 * implementation 'com.squareup.okhttp3:logging-interceptor:4.12.0'
 */
public class ApiExample {

    // ==================== 数据模型 ====================

    /**
     * 用户数据类(Gson 自动解析 JSON)
     */
    public static class User {
        private int id;
        private String name;
        private String email;
        private String phone;

        public User(int id, String name, String email, String phone) {
            this.id = id;
            this.name = name;
            this.email = email;
            this.phone = phone;
        }

        @Override
        public String toString() {
            return "User{id=" + id + ", name='" + name + "', email='" + email + "'}";
        }
    }

    /**
     * 创建用户请求体
     */
    public static class CreateUserRequest {
        private String name;
        private String email;
        private String phone;

        public CreateUserRequest(String name, String email, String phone) {
            this.name = name;
            this.email = email;
            this.phone = phone;
        }
    }

    /**
     * 分页响应
     */
    public static class PaginatedResponse<T> {
        private List<T> data;
        private int page;
        private int perPage;
        private int total;

        public List<T> getData() { return data; }
        public int getPage() { return page; }
        public int getTotal() { return total; }
    }

    // ==================== API 接口定义 ====================

    /**
     * API 接口(前端类比:axios 实例的 methods)
     *
     * Retrofit 通过注解自动将接口方法转换为 HTTP 请求。
     */
    public interface ApiService {

        /**
         * GET /users
         * 前端类比:axios.get('/users')
         */
        @GET("users")
        Call<List<User>> getUsers();

        /**
         * GET /users?page=1&perPage=10
         * 前端类比:axios.get('/users', { params: { page, perPage } })
         */
        @GET("users")
        Call<PaginatedResponse<User>> getUsers(
            @Query("page") int page,
            @Query("perPage") int perPage
        );

        /**
         * GET /users/123
         * 前端类比:axios.get(`/users/${id}`)
         */
        @GET("users/{id}")
        Call<User> getUser(@Path("id") int userId);

        /**
         * POST /users
         * 前端类比:axios.post('/users', userData)
         */
        @POST("users")
        Call<User> createUser(@Body CreateUserRequest user);
    }

    // ==================== Retrofit 客户端 ====================

    /**
     * 创建 Retrofit 实例(前端类比:axios.create())
     */
    public static Retrofit createRetrofit() {
        // 日志拦截器(前端类比:axios 的 request/response 拦截器)
        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(System.out::println);
        loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

        // OkHttpClient(底层 HTTP 客户端)
        OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(loggingInterceptor)
                .addInterceptor(chain -> {
                    // 自定义拦截器:添加认证头
                    okhttp3.Request request = chain.request().newBuilder()
                            .addHeader("Authorization", "Bearer your-token-here")
                            .addHeader("Content-Type", "application/json")
                            .build();
                    return chain.proceed(request);
                })
                .build();

        // Retrofit 实例
        return new Retrofit.Builder()
                .baseUrl("https://api.example.com/")  // 基础 URL
                .client(client)
                .addConverterFactory(GsonConverterFactory.create())  // JSON 解析
                .build();
    }

    // ==================== 使用示例 ====================

    /**
     * 异步请求示例(前端类比:async/await 或 .then())
     */
    public static void fetchUsers(ApiService api) {
        System.out.println("=== 获取用户列表 ===");

        Call<List<User>> call = api.getUsers();

        // 异步执行(前端类比:axios.get('/users').then(...))
        call.enqueue(new Callback<List<User>>() {
            @Override
            public void onResponse(Call<List<User>> call, Response<List<User>> response) {
                if (response.isSuccessful()) {
                    List<User> users = response.body();
                    System.out.println("成功! 用户数量: " + users.size());
                    users.forEach(System.out::println);
                } else {
                    System.out.println("失败: " + response.code());
                }
            }

            @Override
            public void onFailure(Call<List<User>> call, Throwable t) {
                System.out.println("网络错误: " + t.getMessage());
            }
        });
    }

    /**
     * 同步请求示例(前端类比:await axios.get())
     * 注意:不能在 Android 主线程调用!
     */
    public static User fetchUserSync(ApiService api, int userId) throws IOException {
        System.out.println("=== 获取单个用户 (同步) ===");

        Call<User> call = api.getUser(userId);
        Response<User> response = call.execute();  // 阻塞调用

        if (response.isSuccessful()) {
            User user = response.body();
            System.out.println("用户: " + user);
            return user;
        } else {
            throw new IOException("HTTP " + response.code());
        }
    }

    /**
     * 分页请求示例
     */
    public static void fetchUsersPaginated(ApiService api, int page) {
        System.out.println("=== 分页请求 (第 " + page + " 页) ===");

        Call<PaginatedResponse<User>> call = api.getUsers(page, 10);

        call.enqueue(new Callback<PaginatedResponse<User>>() {
            @Override
            public void onResponse(Call<PaginatedResponse<User>> call,
                                   Response<PaginatedResponse<User>> response) {
                if (response.isSuccessful()) {
                    PaginatedResponse<User> result = response.body();
                    System.out.println("第 " + result.getPage() + " 页,共 " + result.getTotal() + " 条");
                    result.getData().forEach(System.out::println);
                }
            }

            @Override
            public void onFailure(Call<PaginatedResponse<User>> call, Throwable t) {
                System.out.println("错误: " + t.getMessage());
            }
        });
    }

    /**
     * POST 请求示例
     */
    public static void createUser(ApiService api) {
        System.out.println("=== 创建用户 ===");

        CreateUserRequest request = new CreateUserRequest(
            "张三", "zhangsan@example.com", "13800138000"
        );

        Call<User> call = api.createUser(request);

        call.enqueue(new Callback<User>() {
            @Override
            public void onResponse(Call<User> call, Response<User> response) {
                if (response.isSuccessful()) {
                    User created = response.body();
                    System.out.println("创建成功: " + created);
                } else {
                    System.out.println("创建失败: " + response.code());
                }
            }

            @Override
            public void onFailure(Call<User> call, Throwable t) {
                System.out.println("网络错误: " + t.getMessage());
            }
        });
    }

    // ==================== 演示入口 ====================

    public static void main(String[] args) {
        // 创建 API 服务
        Retrofit retrofit = createRetrofit();
        ApiService api = retrofit.create(ApiService.class);

        // 演示各种请求
        fetchUsers(api);
        fetchUsersPaginated(api, 1);
        createUser(api);

        // 同步请求(需要在子线程中)
        new Thread(() -> {
            try {
                fetchUserSync(api, 1);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }).start();

        // 保持主线程运行(仅用于演示)
        try { Thread.sleep(5000); } catch (InterruptedException ignored) {}
    }
}

Architecture: MVVM

java
package com.example.architecture;

/**
 * MVVM 架构模式示例
 *
 * MVVM (Model-View-ViewModel) 是 Android 官方推荐的架构模式。
 *
 * 前端类比:
 * - ViewModel = Vue 的 reactive state / React 的 useState
 * - LiveData = Vue 的 ref / React 的状态更新触发重渲染
 * - Repository = Vuex/Pinia 的 actions
 *
 * 依赖配置 (build.gradle):
 * implementation 'androidx.lifecycle:lifecycle-viewmodel:2.7.0'
 * implementation 'androidx.lifecycle:lifecycle-livedata:2.7.0'
 */
public class MVVMExample {

    // ==================== Model 层 ====================

    /**
     * 用户数据模型
     */
    public static class User {
        private int id;
        private String name;
        private String email;

        public User(int id, String name, String email) {
            this.id = id;
            this.name = name;
            this.email = email;
        }

        public int getId() { return id; }
        public String getName() { return name; }
        public String getEmail() { return email; }

        @Override
        public String toString() {
            return name + " (" + email + ")";
        }
    }

    // ==================== Repository 层 ====================

    /**
     * Repository:数据源抽象(前端类比:Vuex actions / API service)
     *
     * 职责:
     * - 决定从哪个数据源获取数据(网络/本地缓存)
     * - 处理数据转换
     * - 对 ViewModel 隐藏数据源细节
     */
    public static class UserRepository {
        // 模拟网络请求
        public User getUser(int userId) {
            // 实际项目中:调用 Retrofit API
            System.out.println("Repository: 从网络获取用户 " + userId);
            return new User(userId, "张三", "zhangsan@example.com");
        }

        // 模拟更新用户
        public boolean updateUser(User user) {
            System.out.println("Repository: 更新用户 " + user.getName());
            return true;
        }
    }

    // ==================== ViewModel 层 ====================

    /**
     * 简化的 LiveData(前端类比:Vue ref / React useState)
     *
     * 实际 Android 中使用:androidx.lifecycle.LiveData
     */
    public static class LiveData<T> {
        private T value;
        private java.util.List<java.util.function.Consumer<T>> observers = new java.util.ArrayList<>();

        public void observe(java.util.function.Consumer<T> observer) {
            observers.add(observer);
            if (value != null) {
                observer.accept(value);
            }
        }

        public void setValue(T newValue) {
            this.value = newValue;
            observers.forEach(observer -> observer.accept(newValue));
        }

        public T getValue() {
            return value;
        }
    }

    /**
     * ViewModel:管理 UI 数据(前端类比:Vue setup() / React 组件状态)
     *
     * 特点:
     * - 生命周期感知:Activity 旋转重建时数据保留
     * - 不持有 View 引用:避免内存泄漏
     * - 职责:准备 UI 数据、处理用户交互
     */
    public static class UserViewModel {
        private final UserRepository repository;

        // UI 状态(前端类比:const user = ref(null))
        private final LiveData<User> user = new LiveData<>();
        private final LiveData<Boolean> isLoading = new LiveData<>();
        private final LiveData<String> errorMessage = new LiveData<>();

        public UserViewModel() {
            this.repository = new UserRepository();
        }

        // 暴露 LiveData 给 View 观察
        public LiveData<User> getUser() { return user; }
        public LiveData<Boolean> getIsLoading() { return isLoading; }
        public LiveData<String> getErrorMessage() { return errorMessage; }

        /**
         * 加载用户(前端类比:const loadUser = async (id) => {...})
         */
        public void loadUser(int userId) {
            isLoading.setValue(true);
            errorMessage.setValue(null);

            // 模拟异步请求(实际项目中用协程或线程池)
            new Thread(() -> {
                try {
                    Thread.sleep(500);  // 模拟网络延迟
                    User loadedUser = repository.getUser(userId);
                    user.setValue(loadedUser);
                    isLoading.setValue(false);
                } catch (Exception e) {
                    errorMessage.setValue("加载失败: " + e.getMessage());
                    isLoading.setValue(false);
                }
            }).start();
        }

        /**
         * 更新用户
         */
        public void updateUser(String newName) {
            User currentUser = user.getValue();
            if (currentUser == null) return;

            isLoading.setValue(true);

            new Thread(() -> {
                User updatedUser = new User(
                    currentUser.getId(),
                    newName,
                    currentUser.getEmail()
                );

                boolean success = repository.updateUser(updatedUser);
                if (success) {
                    user.setValue(updatedUser);
                } else {
                    errorMessage.setValue("更新失败");
                }
                isLoading.setValue(false);
            }).start();
        }
    }

    // ==================== View 层 ====================

    /**
     * 模拟 Activity/Fragment(View 层)
     *
     * 职责:
     * - 显示 UI
     * - 观察 ViewModel 数据变化
     * - 转发用户操作给 ViewModel
     */
    public static class UserView {
        private final UserViewModel viewModel;

        public UserView() {
            viewModel = new UserViewModel();
            setupObservers();
        }

        /**
         * 设置数据观察者(前端类比:watch / useEffect)
         */
        private void setupObservers() {
            // 观察用户数据变化
            viewModel.getUser().observe(user -> {
                System.out.println("View: 显示用户 " + user);
                // 实际项目中:textView.setText(user.getName())
            });

            // 观察加载状态
            viewModel.getIsLoading().observe(isLoading -> {
                if (isLoading) {
                    System.out.println("View: 显示加载动画");
                } else {
                    System.out.println("View: 隐藏加载动画");
                }
            });

            // 观察错误信息
            viewModel.getErrorMessage().observe(error -> {
                if (error != null) {
                    System.out.println("View: 显示错误 " + error);
                }
            });
        }

        /**
         * 模拟用户点击加载按钮
         */
        public void onLoadUserClick(int userId) {
            System.out.println("View: 用户点击加载按钮");
            viewModel.loadUser(userId);
        }

        /**
         * 模拟用户点击更新按钮
         */
        public void onUpdateUserClick(String newName) {
            System.out.println("View: 用户点击更新按钮,新名字: " + newName);
            viewModel.updateUser(newName);
        }
    }

    // ==================== 演示入口 ====================

    public static void main(String[] args) throws InterruptedException {
        System.out.println("=== MVVM 架构演示 ===\n");

        UserView view = new UserView();

        // 模拟用户操作
        view.onLoadUserClick(1);

        Thread.sleep(1000);  // 等待加载完成

        System.out.println();
        view.onUpdateUserClick("李四");

        Thread.sleep(1000);  // 等待更新完成

        System.out.println("\n=== MVVM 数据流 ===");
        System.out.println("User 点击 → View 调用 ViewModel → ViewModel 调用 Repository");
        System.out.println("Repository 返回数据 → ViewModel 更新 LiveData → View 自动刷新");
    }
}

Java → Kotlin Migration Comparison

java
package com.example.migration;

/**
 * 老项目迁移示例:Java → Kotlin 对比
 *
 * 展示同一段代码在 Java 和 Kotlin 中的写法差异,
 * 帮助前端开发者理解 Kotlin 的语法特点。
 */
public class BeforeMigration {

    // ==================== 数据类 ====================

    /**
     * Java 数据类:需要手写 getter/setter/toString/equals/hashCode
     */
    public static class User {
        private int id;
        private String name;
        private String email;
        private boolean isActive;

        public User(int id, String name, String email, boolean isActive) {
            this.id = id;
            this.name = name;
            this.email = email;
            this.isActive = isActive;
        }

        public int getId() { return id; }
        public void setId(int id) { this.id = id; }

        public String getName() { return name; }
        public void setName(String name) { this.name = name; }

        public String getEmail() { return email; }
        public void setEmail(String email) { this.email = email; }

        public boolean isActive() { return isActive; }
        public void setActive(boolean active) { isActive = active; }

        @Override
        public String toString() {
            return "User{id=" + id + ", name='" + name + "', email='" + email + "', isActive=" + isActive + "}";
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) return true;
            if (obj == null || getClass() != obj.getClass()) return false;
            User user = (User) obj;
            return id == user.id;
        }

        @Override
        public int hashCode() {
            return id;
        }
    }

    // ==================== 单例 ====================

    /**
     * Java 单例:需要手写同步和实例管理
     */
    public static class AppConfig {
        private static AppConfig instance;
        private String apiUrl;
        private int timeout;

        private AppConfig() {
            this.apiUrl = "https://api.example.com";
            this.timeout = 30000;
        }

        public static synchronized AppConfig getInstance() {
            if (instance == null) {
                instance = new AppConfig();
            }
            return instance;
        }

        public String getApiUrl() { return apiUrl; }
        public int getTimeout() { return timeout; }
    }

    // ==================== 扩展函数(Java 需要工具类) ====================

    /**
     * Java 工具类:字符串操作
     * Kotlin 中可以直接定义为扩展函数
     */
    public static class StringUtils {
        public static String capitalize(String str) {
            if (str == null || str.isEmpty()) return str;
            return str.substring(0, 1).toUpperCase() + str.substring(1);
        }

        public static boolean isValidEmail(String email) {
            return email != null && email.contains("@") && email.contains(".");
        }

        public static String truncate(String str, int maxLength) {
            if (str == null || str.length() <= maxLength) return str;
            return str.substring(0, maxLength) + "...";
        }
    }

    // ==================== 回调接口 ====================

    /**
     * Java 回调接口(Kotlin 可以用高阶函数替代)
     */
    public interface Callback<T> {
        void onSuccess(T result);
        void onError(String error);
    }

    /**
     * 使用回调的异步操作
     */
    public static void fetchData(int id, Callback<String> callback) {
        new Thread(() -> {
            try {
                Thread.sleep(100);
                callback.onSuccess("数据 " + id);
            } catch (InterruptedException e) {
                callback.onError("中断: " + e.getMessage());
            }
        }).start();
    }

    // ==================== 演示 ====================

    public static void main(String[] args) {
        System.out.println("=== Java 版本 ===\n");

        // 数据类
        User user = new User(1, "张三", "zhangsan@example.com", true);
        System.out.println(user);

        // 单例
        AppConfig config = AppConfig.getInstance();
        System.out.println("API URL: " + config.getApiUrl());

        // 工具类
        System.out.println("capitalize: " + StringUtils.capitalize("hello"));
        System.out.println("isValidEmail: " + StringUtils.isValidEmail("a@b.c"));

        // 回调
        fetchData(42, new Callback<String>() {
            @Override
            public void onSuccess(String result) {
                System.out.println("成功: " + result);
            }

            @Override
            public void onError(String error) {
                System.out.println("错误: " + error);
            }
        });
    }
}

/**
 * Kotlin 版本(仅供参考,实际应在 .kt 文件中)
 *
 * ```kotlin
 * // 数据类:自动生成 getter/setter/toString/equals/hashCode
 * data class User(
 *     val id: Int,
 *     var name: String,
 *     var email: String,
 *     var isActive: Boolean = true
 * )
 *
 * // 单例:object 关键字
 * object AppConfig {
 *     val apiUrl = "https://api.example.com"
 *     val timeout = 30000
 * }
 *
 * // 扩展函数
 * fun String.capitalize(): String =
 *     this.replaceFirstChar { it.uppercase() }
 *
 * fun String.isValidEmail(): Boolean =
 *     this.contains("@") && this.contains(".")
 *
 * fun String.truncate(maxLength: Int): String =
 *     if (length <= maxLength) this else "${take(maxLength)}..."
 *
 * // 高阶函数(替代回调接口)
 * fun fetchData(
 *     id: Int,
 *     onSuccess: (String) -> Unit,
 *     onError: (String) -> Unit
 * ) {
 *     thread {
 *         try {
 *             Thread.sleep(100)
 *             onSuccess("数据 $id")
 *         } catch (e: InterruptedException) {
 *             onError("中断: ${e.message}")
 *         }
 *     }
 * }
 *
 * // 使用
 * fun main() {
 *     val user = User(1, "张三", "zhangsan@example.com")
 *     println(user)
 *
 *     println(AppConfig.apiUrl)
 *
 *     println("hello".capitalize())
 *     println("a@b.c".isValidEmail())
 *
 *     fetchData(
 *         id = 42,
 *         onSuccess = { result -> println("成功: $result") },
 *         onError = { error -> println("错误: $error") }
 *     )
 * }
 * ```
 */

A Java Android development tutorial for frontend developers