引言

在Android应用开发中,跨Activity的数据传递和界面更新是开发者经常面临的挑战。由于Android的Activity生命周期管理机制,直接调用另一个Activity的方法并不推荐,这会导致紧耦合和潜在的内存泄漏问题。本文将深入探讨几种安全、高效的跨Activity通信方式,包括使用Intent传递数据、startActivityForResult机制、ViewModel共享数据、EventBus事件总线等,并详细分析常见错误及其处理技巧。

1. 使用Intent传递数据(基础方式)

1.1 基本原理

Intent是Android组件间通信的核心机制,通过Bundle携带数据,支持基本数据类型和实现了Parcelable/Serializable接口的对象。

1.2 代码示例:传递基本数据类型

// 发送Activity (MainActivity.java)
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        Button btnNavigate = findViewById(R.id.btn_navigate);
        btnNavigate.setOnClickListener(v -> {
            // 创建Intent,指定当前Activity和目标Activity
            Intent intent = new Intent(MainActivity.this, DetailActivity.class);
            
            // 携带基本数据类型
            intent.putExtra("USER_ID", 1001);
            intent.putExtra("USER_NAME", "张三");
            intent.putExtra("SCORE", 95.5);
            
            // 启动目标Activity
            startActivity(intent);
        });
    }
}

// 接收Activity (DetailActivity.java)
public class DetailActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_detail);
        
        // 从Intent获取数据
        Intent intent = getIntent();
        if (intent != null) {
            int userId = intent.getIntExtra("USER_ID", -1);
            String userName = intent.getStringExtra("USER_NAME");
            double score = intent.getDoubleExtra("SCORE", 0.0);
            
            // 更新UI
            TextView tvInfo = findViewById(R.id.tv_info);
            tvInfo.setText(String.format("用户ID: %d\n姓名: %s\n分数: %.1f", 
                userId, userName, score));
        }
    }
}

1.3 传递自定义对象(Parcelable实现)

// 自定义User对象,实现Parcelable接口
public class User implements Parcelable {
    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;
    }

    // Parcelable实现
    protected User(Parcel in) {
        id = in.readInt();
        name = in.readString();
        email = in.readString();
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(id);
        dest.writeString(name);
        dest.writeString(email);
    }

    @Override
    public int describeContents() {
        return 0;
    }

    public static final Creator<User> CREATOR = new Creator<User>() {
        @Override
        public User createFromParcel(Parcel in) {
            return new User(in);
        }

        @Override
        public User[] newArray(int size) {
            return new User[size];
        }
    };

    // Getter方法
    public int getId() { return id; }
    public String getName() { return name; }
    public String getEmail() { return email; }
}

// 发送Activity
public class MainActivity extends AppCompatActivity {
    private void navigateWithUser() {
        User user = new User(1001, "李四", "lisi@example.com");
        Intent intent = new Intent(this, DetailActivity.class);
        intent.putExtra("USER", user); // 直接传递Parcelable对象
        startActivity(intent);
    }
}

// 接收Activity
public class DetailActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_detail);
        
        User user = getIntent().getParcelableExtra("USER");
        if (user != null) {
            // 使用user对象更新UI
            updateUI(user);
        }
    }
}

1.4 优缺点分析

优点:

  • 简单直接,适合一次性数据传递
  • 系统级支持,性能较好
  • 无需额外依赖库

缺点:

  • 只能传递实现了Parcelable/Serializable接口的对象
  • 数据量大时Bundle大小受限(约50KB)
  • 无法传递生命周期长的对象,容易导致内存泄漏

2. startActivityForResult机制(双向通信)

2.1 基本原理

通过startActivityForResult()启动Activity,在目标Activity完成后调用setResult()返回数据,原Activity通过onActivityResult()接收结果。

2.2 代码示例:用户选择场景

// MainActivity.java
public class MainActivity extends AppCompatActivity {
    private static final int REQUEST_CODE_SELECT_USER = 100;
    private TextView tvSelectedUser;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        tvSelectedUser = findViewById(R.id.tv_selected_user);
        Button btnSelectUser = findViewById(R.id.btn_select_user);
        
        btnSelectUser.setOnClickListener(v -> {
            Intent intent = new Intent(this, UserSelectActivity.class);
            // 启动并等待结果
            startActivityForResult(intent, REQUEST_CODE_SELECT_USER);
        });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        
        if (requestCode == REQUEST_CODE_SELECT_USER && resultCode == RESULT_OK && data != null) {
            // 接收返回的用户数据
            User selectedUser = data.getParcelableExtra("SELECTED_USER");
            if (selectedUser != null) {
                tvSelectedUser.setText("选中用户: " + selectedUser.getName());
            }
        } else if (resultCode == RESULT_CANCELED) {
            // 用户取消选择
            Toast.makeText(this, "已取消选择", Toast.LENGTH_SHORT).show();
        }
    }
}

// UserSelectActivity.java
public class UserSelectActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_user_select);
        
        Button btnSelectAlice = findViewById(R.id.btn_select_alice);
        Button btnSelectBob = findViewById(R.id.btn_select_bob);
        
        btnSelectAlice.setOnClickListener(v -> {
            // 创建结果数据
            User alice = new User(1, "Alice", "alice@example.com");
            Intent resultIntent = new Intent();
            resultIntent.putExtra("SELECTED_USER", alice);
            
            // 设置结果并结束当前Activity
            setResult(RESULT_OK, resultIntent);
            finish();
        });
        
        btnSelectBob.setOnClickListener(v -> {
            User bob = new User(2, "Bob", "bob@example.com");
            Intent resultIntent = new Intent();
            resultIntent.putExtra("SELECTED_USER", bob);
            setResult(RESULT_OK, resultIntent);
            finish();
        });
        
        // 取消按钮
        findViewById(R.id.btn_cancel).setOnClickListener(v -> {
            setResult(RESULT_CANCELED);
            finish();
        });
    }
}

2.3 优缺点分析

优点:

  • 支持双向通信,适合需要用户交互后返回结果的场景
  • 生命周期管理相对简单

缺点:

  • 回调地狱(Callback Hell)风险
  • 代码耦合度较高
  • 在Activity结果返回前,原Activity可能已被销毁,导致内存泄漏

3. ViewModel + LiveData(现代推荐方式)

3.1 基本原理

ViewModel以生命周期感知的方式存储和管理界面相关数据,LiveData则提供可观察的数据存储器。多个Activity/Fragment可以共享同一个ViewModel实例(通过ViewModelStoreOwner)。

3.2 代码示例:共享数据模型

// SharedViewModel.java
public class SharedViewModel extends ViewModel {
    // 使用LiveData存储用户数据
    private final MutableLiveData<User> selectedUser = new MutableLiveData<>();
    private final MutableLiveData<String> message = new MutableLiveData<>();

    public void selectUser(User user) {
        selectedUser.setValue(user);
    }

    public LiveData<User> getSelectedUser() {
        return selectedUser;
    }

    public void sendMessage(String msg) {
        message.setValue(msg);
    }

    public LiveData<String> getMessage() {
        return message;
    }
}

// MainActivity.java
public class MainActivity extends AppCompatActivity {
    private SharedViewModel viewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        // 获取ViewModel实例(作用域为Activity)
        viewModel = new ViewModelProvider(this).get(SharedViewModel.class);
        
        Button btnNavigate = findViewById(R.id.btn_navigate);
        btnNavigate.setOnClickListener(v -> {
            // 在跳转前设置数据
            User user = new User(1001, "张三", "zhangsan@example.com");
            viewModel.selectUser(user);
            
            // 启动新Activity
            startActivity(new Intent(this, DetailActivity.class));
        });
        
        // 观察数据变化(可选,用于接收返回数据)
        viewModel.getMessage().observe(this, msg -> {
            if (msg != null) {
                Toast.makeText(this, "收到消息: " + msg, Toast.LENGTH_SHORT).show();
            }
        });
    }
}

// DetailActivity.java
public class DetailActivity extends AppCompatActivity {
    private SharedViewModel viewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_detail);
        
        // 获取同一个ViewModel实例
        viewModel = new ViewModelProvider(this).get(SharedViewModel.class);
        
        // 观察用户数据变化
        viewModel.getSelectedUser().observe(this, user -> {
            if (user != null) {
                // 更新UI
                TextView tvInfo = findViewById(R.id.tv_info);
                tvInfo.setText(String.format("用户ID: %d\n姓名: %s\n邮箱: %s", 
                    user.getId(), user.getName(), user.getEmail()));
            }
        });
        
        // 发送反馈消息回MainActivity
        Button btnSendFeedback = findViewById(R.id.btn_send_feedback);
        btnSendFeedback.setOnClickListener(v -> {
            viewModel.sendMessage("DetailActivity操作完成");
            finish(); // 结束当前Activity
        });
    }
}

3.3 优缺点分析

优点:

  • 生命周期感知,自动处理配置更改(如屏幕旋转)
  • 数据驱动UI更新,代码更清晰
  • 支持多Fragment/Activity共享数据
  • 无内存泄漏风险

缺点:

  • 需要AndroidX依赖
  • 仅适用于同一应用内通信
  • 对于简单数据传递可能显得复杂

4. EventBus(事件总线模式)

4.1 基本原理

EventBus是一个基于发布-订阅模式的开源库,允许组件通过事件进行通信,无需显式引用彼此。

4.2 代码示例:事件驱动通信

// 1. 定义事件类
public class UserEvent {
    private User user;
    private String action;

    public UserEvent(User user, String action) {
        this.user = user;
        this.action = action;
    }

    public User getUser() { return user; }
    public String getAction() { return action; }
}

// 2. 发送事件的Activity
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        Button btnSendEvent = findViewById(R.id.btn_send_event);
        btnSendEvent.setOnClickListener(v -> {
            User user = new User(1001, "EventBus用户", "event@example.com");
            // 发布事件
            EventBus.getDefault().post(new UserEvent(user, "UPDATE"));
            
            // 启动新Activity(可选)
            startActivity(new Intent(this, DetailActivity.class));
        });
    }

    @Override
    protected void onStart() {
        super.onStart();
        EventBus.getDefault().register(this);
    }

    @Override
    protected void onStop() {
        super.onStop();
        EventBus.getDefault().unregister(this);
    }

    // 接收事件的方法
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onUserEvent(UserEvent event) {
        Toast.makeText(this, "MainActivity收到事件: " + event.getAction(), 
            Toast.LENGTH_SHORT).show();
    }
}

// 3. 接收事件的Activity
public class DetailActivity extends AppCompatActivity {
    private TextView tvEventInfo;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_detail);
        tvEventInfo = findViewById(R.id.tv_event_info);
    }

    @Override
    protected void onStart() {
        super.onStart();
        EventBus.getDefault().register(this);
    }

    @Override
    protected void onStop() {
        super.onStop();
        EventBus.getDefault().unregister(this);
    }

    // 接收事件并更新UI
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onUserEvent(UserEvent event) {
        if ("UPDATE".equals(event.getAction())) {
            User user = event.getUser();
            tvEventInfo.setText(String.format("EventBus接收:\n用户: %s\n邮箱: %s", 
                user.getName(), user.getEmail()));
        }
    }
}

4.3 依赖配置

// app/build.gradle
dependencies {
    implementation 'org.greenrobot:eventbus:3.3.1'
}

4.4 优缺点分析

优点:

  • 解耦彻底,组件间无引用关系
  • 支持线程切换(ThreadMode)
  • 事件可被多个订阅者接收
  • 适合全局事件通知

缺点:

  • 增加依赖库
  • 事件类型定义需谨慎,避免命名冲突
  • 调试困难(事件流不直观)
  • 可能导致”事件风暴”(过度使用事件总线)

5. 其他通信方式

5.1 静态方法调用(不推荐)

// 不推荐的方式:直接调用静态方法
public class DataHolder {
    private static User currentUser;
    
    public static void setCurrentUser(User user) {
        currentUser = user;
    }
    
    public static User getCurrentUser() {
        return currentUser;
    }
}

// 在Activity中使用
public class MainActivity extends AppCompatActivity {
    private void navigate() {
        // 设置数据
        DataHolder.setCurrentUser(new User(1, "Test", "test@example.com"));
        
        // 跳转
        startActivity(new Intent(this, DetailActivity.class));
    }
}

public class DetailActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 获取数据
        User user = DataHolder.getCurrentUser();
        // 使用数据...
    }
}

问题:内存泄漏风险,无法自动清理,不适合复杂场景。

5.2 单例模式存储

// 单例数据管理器
public class DataManager {
    private static DataManager instance;
    private final Map<String, Object> dataMap = new HashMap<>();
    
    private DataManager() {}
    
    public static DataManager getInstance() {
        if (instance == null) {
            synchronized (DataManager.class) {
                if (instance == null) {
                    instance = new DataManager();
                }
            }
        }
        return instance;
    }
    
    public void putData(String key, Object value) {
        dataMap.put(key, value);
    }
    
    public Object getData(String key) {
        return dataMap.remove(key); // 使用后立即移除,避免内存泄漏
    }
}

注意:必须及时清理数据,否则会导致内存泄漏。

6. 常见错误及处理技巧

6.1 错误1:TransactionTooLargeException(数据传递过大)

问题描述: Android 7.0+限制了Intent传递的数据大小(约1MB),超过限制会抛出TransactionTooLargeException。

解决方案:

// 错误示例:传递大量数据
Intent intent = new Intent(this, DetailActivity.class);
intent.putExtra("LARGE_LIST", (Serializable) largeDataList); // 可能崩溃

// 正确做法1:传递引用ID,通过单例或数据库获取数据
public class DataCache {
    private static final Map<Integer, List<LargeData>> cache = new HashMap<>();
    private static int idCounter = 0;
    
    public static int storeData(List<LargeData> data) {
        int id = idCounter++;
        cache.put(id, data);
        return id;
    }
    
    public static List<LargeData> getData(int id) {
        return cache.remove(id); // 使用后立即清理
    }
}

// 使用
int dataId = DataCache.storeData(largeDataList);
Intent intent = new Intent(this, DetailActivity.class);
intent.putExtra("DATA_ID", dataId);
startActivity(intent);

// 正确做法2:使用文件/数据库存储
// 将数据序列化到文件,传递文件路径

6.2 错误2:内存泄漏(Memory Leak)

问题描述: 在Activity中启动新Activity时,如果持有新Activity的引用或回调,会导致旧Activity无法被回收。

错误示例:

public class MainActivity extends AppCompatActivity {
    private DetailActivity detailActivity; // 错误:持有Activity引用
    
    private void navigate() {
        Intent intent = new Intent(this, DetailActivity.class);
        startActivity(intent);
        // 错误:直接引用会导致内存泄漏
        detailActivity = new DetailActivity(); // 不应该手动创建
    }
}

解决方案:

// 1. 使用弱引用(WeakReference)
public class MainActivity extends AppCompatActivity {
    private WeakReference<DetailActivity> detailActivityRef;
    
    private void navigate() {
        Intent intent = new Intent(this, DetailActivity.class);
        startActivity(intent);
        // 如果必须引用,使用弱引用
        // detailActivityRef = new WeakReference<>(detailActivity);
    }
}

// 2. 更好的做法:使用ViewModel或事件总线,避免直接引用
// 3. 在onDestroy中清理
@Override
protected void onDestroy() {
    super.onDestroy();
    // 清理所有可能泄漏的引用
    detailActivityRef = null;
}

6.3 错误3:NullPointerException(空指针异常)

问题描述: 接收数据时未检查Intent或数据是否为null。

解决方案:

// 错误示例
public class DetailActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 直接使用,可能NPE
        String name = getIntent().getStringExtra("USER_NAME");
        TextView tv = findViewById(R.id.tv_name);
        tv.setText(name); // 如果name为null,显示"null"
    }
}

// 正确做法:防御性编程
public class DetailActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_detail);
        
        Intent intent = getIntent();
        if (intent == null) {
            finish(); // 没有Intent,直接结束
            return;
        }
        
        String name = intent.getStringExtra("USER_NAME");
        if (name == null) {
            name = "默认用户"; // 提供默认值
        }
        
        TextView tv = findViewById(R.id.tv_name);
        if (tv != null) {
            tv.setText(name);
        }
        
        // 或者使用更简洁的方式
        String safeName = Objects.requireNonNullElse(intent.getStringExtra("USER_NAME"), "默认用户");
        tv.setText(safeName);
    }
}

6.4 错误4:ViewModel作用域混淆

问题描述: 在不同Activity中获取ViewModel时,作用域设置错误导致数据不共享。

错误示例:

// MainActivity
SharedViewModel viewModel1 = new ViewModelProvider(this).get(SharedViewModel.class);

// DetailActivity
SharedViewModel viewModel2 = new ViewModelProvider(this).get(SharedViewModel.class);
// 这两个ViewModel实例是不同的!

解决方案:

// 正确做法:使用同一个ViewModelStoreOwner
// 方法1:在Application级别共享(不推荐,可能导致内存泄漏)
public class MyApplication extends Application implements ViewModelStoreOwner {
    private ViewModelStore appViewModelStore;
    
    @Override
    public ViewModelStore getViewModelStore() {
        if (appViewModelStore == null) {
            appViewModelStore = new ViewModelStore();
        }
        return appViewModelStore;
    }
}

// 在Activity中获取
SharedViewModel viewModel = new ViewModelProvider(
    (ViewModelStoreOwner) getApplication()).get(SharedViewModel.class);

// 方法2:使用ActivityResultRegistry(推荐)
public class MainActivity extends AppCompatActivity {
    private final ActivityResultRegistry registry = new ActivityResultRegistry();
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        // 使用ActivityResultLauncher
        ActivityResultLauncher<Intent> launcher = registerForActivityResult(
            new ActivityResultContracts.StartActivityForResult(),
            result -> {
                if (result.getResultCode() == RESULT_OK && result.getData() != null) {
                    // 处理结果
                }
            });
    }
}

6.5 错误5:生命周期不匹配

问题描述: 在Activity的onCreate()中访问尚未初始化的视图或数据。

解决方案:

// 错误示例
public class DetailActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 错误:在setContentView之前访问视图
        TextView tv = findViewById(R.id.tv_info); // 返回null
        tv.setText("Hello"); // NPE
        
        setContentView(R.layout.activity_detail);
    }
}

// 正确做法
public class DetailActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_detail); // 先设置布局
        
        // 再访问视图
        TextView tv = findViewById(R.id.tv_info);
        if (tv != null) {
            tv.setText("Hello");
        }
        
        // 处理数据
        handleIntentData();
    }
    
    private void handleIntentData() {
        Intent intent = getIntent();
        if (intent == null) return;
        
        // 延迟处理数据,确保视图已初始化
        if (savedInstanceState == null) {
            // 只在首次创建时处理
            processIntentData(intent);
        }
    }
}

6.6 错误6:重复注册监听器

问题描述: 在onCreate()中注册EventBus或LiveData监听器,但未在onDestroy()中注销,导致重复注册和内存泄漏。

解决方案:

// EventBus正确注册/注销
@Override
protected void onStart() {
    super.onStart();
    if (!EventBus.getDefault().isRegistered(this)) {
        EventBus.getDefault().register(this);
    }
}

@Override
protected void onStop() {
    super.onStop();
    if (EventBus.getDefault().isRegistered(this)) {
        EventBus.getDefault().unregister(this);
    }
}

// LiveData正确观察
private void setupObservers() {
    // 使用viewLifecycleOwner(在Fragment中)
    // 在Activity中使用this
    viewModel.getData().observe(this, data -> {
        // 更新UI
    });
}

// 避免重复观察
private boolean isObserverSetup = false;
private void setupObservers() {
    if (isObserverSetup) return;
    isObserverSetup = true;
    // 设置观察器...
}

6.7 错误7:混淆onActivityResult与新API

问题描述: AndroidX推荐使用ActivityResultLauncher替代startActivityForResult,但开发者仍使用旧API。

解决方案:

// 旧API(已废弃)
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    // 处理结果...
}

// 新API(推荐)
public class MainActivity extends AppCompatActivity {
    // 定义Launcher
    private ActivityResultLauncher<Intent> userSelectLauncher;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        // 注册Launcher
        userSelectLauncher = registerForActivityResult(
            new ActivityResultContracts.StartActivityForResult(),
            result -> {
                if (result.getResultCode() == RESULT_OK && result.getData() != null) {
                    User user = result.getData().getParcelableExtra("SELECTED_USER");
                    if (user != null) {
                        // 更新UI
                        TextView tv = findViewById(R.id.tv_selected_user);
                        tv.setText("选中: " + user.getName());
                    }
                }
            });
        
        Button btnSelect = findViewById(R.id.btn_select);
        btnSelect.setOnClickListener(v -> {
            Intent intent = new Intent(this, UserSelectActivity.class);
            userSelectLauncher.launch(intent);
        });
    }
}

7. 最佳实践总结

7.1 选择策略

  • 简单数据传递:使用Intent + Parcelable
  • 双向通信/结果返回:使用ActivityResultLauncher
  • 多Fragment/Activity共享数据:使用ViewModel + LiveData
  • 全局事件通知:使用EventBus(谨慎使用)
  • 避免:静态变量、单例直接存储Activity引用

7.2 性能优化

// 1. 使用SparseArray替代HashMap(针对整数键)
SparseArray<User> userCache = new SparseArray<>();

// 2. 延迟初始化
private TextView tvInfo;
private TextView getTvInfo() {
    if (tvInfo == null) {
        tvInfo = findViewById(R.id.tv_info);
    }
    return tvInfo;
}

// 3. 使用LruCache缓存对象
private LruCache<Integer, User> userCache = new LruCache<>(100);

// 4. 异步处理大数据
private void processLargeDataAsync(List<LargeData> data) {
    new Thread(() -> {
        // 耗时操作
        List<Result> results = processData(data);
        
        // 回到主线程更新UI
        runOnUiThread(() -> updateUI(results));
    }).start();
}

7.3 安全性考虑

// 1. 数据验证
public class SecureDataTransmitter {
    public static boolean validateUserData(User user) {
        if (user == null) return false;
        if (user.getId() <= 0) return false;
        if (user.getName() == null || user.getName().isEmpty()) return false;
        return true;
    }
}

// 2. 防止Intent注入
public class SafeActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        Intent intent = getIntent();
        if (intent != null && intent.getData() != null) {
            // 验证URI来源
            Uri data = intent.getData();
            if (!isValidUri(data)) {
                finish();
                return;
            }
        }
    }
    
    private boolean isValidUri(Uri uri) {
        // 检查URI是否来自可信来源
        return "com.yourapp".equals(uri.getHost());
    }
}

7.4 调试技巧

// 1. 添加日志追踪数据流
public class DebugDataTransmitter {
    private static final String TAG = "DataFlow";
    
    public static void logDataTransfer(String from, String to, Object data) {
        Log.d(TAG, String.format("Transfer: %s -> %s, Data: %s", 
            from, to, data != null ? data.getClass().getSimpleName() : "null"));
    }
}

// 2. 使用StrictMode检测问题
public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        
        if (BuildConfig.DEBUG) {
            StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                .detectAll()
                .penaltyLog()
                .build());
            
            StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                .detectAll()
                .penaltyLog()
                .build());
        }
    }
}

8. 总结

跨Activity通信是Android开发的核心技能,选择合适的方案取决于具体场景:

  1. Intent传递:适合简单、一次性数据传递
  2. ActivityResultLauncher:适合需要返回结果的交互场景
  3. ViewModel:现代推荐方式,适合共享数据和配置更改
  4. EventBus:适合解耦的全局事件,但需谨慎使用

关键原则:

  • 避免直接引用Activity实例
  • 及时清理资源,防止内存泄漏
  • 做好空值检查和异常处理
  • 遵循Android生命周期规范
  • 优先使用AndroidX推荐的新API

通过合理选择通信方式并遵循最佳实践,可以构建出健壮、高效、可维护的Android应用。# Android开发中如何跨Activity调用方法解决数据传递与界面更新问题及常见错误处理技巧

引言

在Android应用开发中,跨Activity的数据传递和界面更新是开发者经常面临的挑战。由于Android的Activity生命周期管理机制,直接调用另一个Activity的方法并不推荐,这会导致紧耦合和潜在的内存泄漏问题。本文将深入探讨几种安全、高效的跨Activity通信方式,包括使用Intent传递数据、startActivityForResult机制、ViewModel共享数据、EventBus事件总线等,并详细分析常见错误及其处理技巧。

1. 使用Intent传递数据(基础方式)

1.1 基本原理

Intent是Android组件间通信的核心机制,通过Bundle携带数据,支持基本数据类型和实现了Parcelable/Serializable接口的对象。

1.2 代码示例:传递基本数据类型

// 发送Activity (MainActivity.java)
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        Button btnNavigate = findViewById(R.id.btn_navigate);
        btnNavigate.setOnClickListener(v -> {
            // 创建Intent,指定当前Activity和目标Activity
            Intent intent = new Intent(MainActivity.this, DetailActivity.class);
            
            // 携带基本数据类型
            intent.putExtra("USER_ID", 1001);
            intent.putExtra("USER_NAME", "张三");
            intent.putExtra("SCORE", 95.5);
            
            // 启动目标Activity
            startActivity(intent);
        });
    }
}

// 接收Activity (DetailActivity.java)
public class DetailActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_detail);
        
        // 从Intent获取数据
        Intent intent = getIntent();
        if (intent != null) {
            int userId = intent.getIntExtra("USER_ID", -1);
            String userName = intent.getStringExtra("USER_NAME");
            double score = intent.getDoubleExtra("SCORE", 0.0);
            
            // 更新UI
            TextView tvInfo = findViewById(R.id.tv_info);
            tvInfo.setText(String.format("用户ID: %d\n姓名: %s\n分数: %.1f", 
                userId, userName, score));
        }
    }
}

1.3 传递自定义对象(Parcelable实现)

// 自定义User对象,实现Parcelable接口
public class User implements Parcelable {
    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;
    }

    // Parcelable实现
    protected User(Parcel in) {
        id = in.readInt();
        name = in.readString();
        email = in.readString();
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(id);
        dest.writeString(name);
        dest.writeString(email);
    }

    @Override
    public int describeContents() {
        return 0;
    }

    public static final Creator<User> CREATOR = new Creator<User>() {
        @Override
        public User createFromParcel(Parcel in) {
            return new User(in);
        }

        @Override
        public User[] newArray(int size) {
            return new User[size];
        }
    };

    // Getter方法
    public int getId() { return id; }
    public String getName() { return name; }
    public String getEmail() { return email; }
}

// 发送Activity
public class MainActivity extends AppCompatActivity {
    private void navigateWithUser() {
        User user = new User(1001, "李四", "lisi@example.com");
        Intent intent = new Intent(this, DetailActivity.class);
        intent.putExtra("USER", user); // 直接传递Parcelable对象
        startActivity(intent);
    }
}

// 接收Activity
public class DetailActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_detail);
        
        User user = getIntent().getParcelableExtra("USER");
        if (user != null) {
            // 使用user对象更新UI
            updateUI(user);
        }
    }
}

1.4 优缺点分析

优点:

  • 简单直接,适合一次性数据传递
  • 系统级支持,性能较好
  • 无需额外依赖库

缺点:

  • 只能传递实现了Parcelable/Serializable接口的对象
  • 数据量大时Bundle大小受限(约50KB)
  • 无法传递生命周期长的对象,容易导致内存泄漏

2. startActivityForResult机制(双向通信)

2.1 基本原理

通过startActivityForResult()启动Activity,在目标Activity完成后调用setResult()返回数据,原Activity通过onActivityResult()接收结果。

2.2 代码示例:用户选择场景

// MainActivity.java
public class MainActivity extends AppCompatActivity {
    private static final int REQUEST_CODE_SELECT_USER = 100;
    private TextView tvSelectedUser;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        tvSelectedUser = findViewById(R.id.tv_selected_user);
        Button btnSelectUser = findViewById(R.id.btn_select_user);
        
        btnSelectUser.setOnClickListener(v -> {
            Intent intent = new Intent(this, UserSelectActivity.class);
            // 启动并等待结果
            startActivityForResult(intent, REQUEST_CODE_SELECT_USER);
        });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        
        if (requestCode == REQUEST_CODE_SELECT_USER && resultCode == RESULT_OK && data != null) {
            // 接收返回的用户数据
            User selectedUser = data.getParcelableExtra("SELECTED_USER");
            if (selectedUser != null) {
                tvSelectedUser.setText("选中用户: " + selectedUser.getName());
            }
        } else if (resultCode == RESULT_CANCELED) {
            // 用户取消选择
            Toast.makeText(this, "已取消选择", Toast.LENGTH_SHORT).show();
        }
    }
}

// UserSelectActivity.java
public class UserSelectActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_user_select);
        
        Button btnSelectAlice = findViewById(R.id.btn_select_alice);
        Button btnSelectBob = findViewById(R.id.btn_select_bob);
        
        btnSelectAlice.setOnClickListener(v -> {
            // 创建结果数据
            User alice = new User(1, "Alice", "alice@example.com");
            Intent resultIntent = new Intent();
            resultIntent.putExtra("SELECTED_USER", alice);
            
            // 设置结果并结束当前Activity
            setResult(RESULT_OK, resultIntent);
            finish();
        });
        
        btnSelectBob.setOnClickListener(v -> {
            User bob = new User(2, "Bob", "bob@example.com");
            Intent resultIntent = new Intent();
            resultIntent.putExtra("SELECTED_USER", bob);
            setResult(RESULT_OK, resultIntent);
            finish();
        });
        
        // 取消按钮
        findViewById(R.id.btn_cancel).setOnClickListener(v -> {
            setResult(RESULT_CANCELED);
            finish();
        });
    }
}

2.3 优缺点分析

优点:

  • 支持双向通信,适合需要用户交互后返回结果的场景
  • 生命周期管理相对简单

缺点:

  • 回调地狱(Callback Hell)风险
  • 代码耦合度较高
  • 在Activity结果返回前,原Activity可能已被销毁,导致内存泄漏

3. ViewModel + LiveData(现代推荐方式)

3.1 基本原理

ViewModel以生命周期感知的方式存储和管理界面相关数据,LiveData则提供可观察的数据存储器。多个Activity/Fragment可以共享同一个ViewModel实例(通过ViewModelStoreOwner)。

3.2 代码示例:共享数据模型

// SharedViewModel.java
public class SharedViewModel extends ViewModel {
    // 使用LiveData存储用户数据
    private final MutableLiveData<User> selectedUser = new MutableLiveData<>();
    private final MutableLiveData<String> message = new MutableLiveData<>();

    public void selectUser(User user) {
        selectedUser.setValue(user);
    }

    public LiveData<User> getSelectedUser() {
        return selectedUser;
    }

    public void sendMessage(String msg) {
        message.setValue(msg);
    }

    public LiveData<String> getMessage() {
        return message;
    }
}

// MainActivity.java
public class MainActivity extends AppCompatActivity {
    private SharedViewModel viewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        // 获取ViewModel实例(作用域为Activity)
        viewModel = new ViewModelProvider(this).get(SharedViewModel.class);
        
        Button btnNavigate = findViewById(R.id.btn_navigate);
        btnNavigate.setOnClickListener(v -> {
            // 在跳转前设置数据
            User user = new User(1001, "张三", "zhangsan@example.com");
            viewModel.selectUser(user);
            
            // 启动新Activity
            startActivity(new Intent(this, DetailActivity.class));
        });
        
        // 观察数据变化(可选,用于接收返回数据)
        viewModel.getMessage().observe(this, msg -> {
            if (msg != null) {
                Toast.makeText(this, "收到消息: " + msg, Toast.LENGTH_SHORT).show();
            }
        });
    }
}

// DetailActivity.java
public class DetailActivity extends AppCompatActivity {
    private SharedViewModel viewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_detail);
        
        // 获取同一个ViewModel实例
        viewModel = new ViewModelProvider(this).get(SharedViewModel.class);
        
        // 观察用户数据变化
        viewModel.getSelectedUser().observe(this, user -> {
            if (user != null) {
                // 更新UI
                TextView tvInfo = findViewById(R.id.tv_info);
                tvInfo.setText(String.format("用户ID: %d\n姓名: %s\n邮箱: %s", 
                    user.getId(), user.getName(), user.getEmail()));
            }
        });
        
        // 发送反馈消息回MainActivity
        Button btnSendFeedback = findViewById(R.id.btn_send_feedback);
        btnSendFeedback.setOnClickListener(v -> {
            viewModel.sendMessage("DetailActivity操作完成");
            finish(); // 结束当前Activity
        });
    }
}

3.3 优缺点分析

优点:

  • 生命周期感知,自动处理配置更改(如屏幕旋转)
  • 数据驱动UI更新,代码更清晰
  • 支持多Fragment/Activity共享数据
  • 无内存泄漏风险

缺点:

  • 需要AndroidX依赖
  • 仅适用于同一应用内通信
  • 对于简单数据传递可能显得复杂

4. EventBus(事件总线模式)

4.1 基本原理

EventBus是一个基于发布-订阅模式的开源库,允许组件通过事件进行通信,无需显式引用彼此。

4.2 代码示例:事件驱动通信

// 1. 定义事件类
public class UserEvent {
    private User user;
    private String action;

    public UserEvent(User user, String action) {
        this.user = user;
        this.action = action;
    }

    public User getUser() { return user; }
    public String getAction() { return action; }
}

// 2. 发送事件的Activity
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        Button btnSendEvent = findViewById(R.id.btn_send_event);
        btnSendEvent.setOnClickListener(v -> {
            User user = new User(1001, "EventBus用户", "event@example.com");
            // 发布事件
            EventBus.getDefault().post(new UserEvent(user, "UPDATE"));
            
            // 启动新Activity(可选)
            startActivity(new Intent(this, DetailActivity.class));
        });
    }

    @Override
    protected void onStart() {
        super.onStart();
        EventBus.getDefault().register(this);
    }

    @Override
    protected void onStop() {
        super.onStop();
        EventBus.getDefault().unregister(this);
    }

    // 接收事件的方法
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onUserEvent(UserEvent event) {
        Toast.makeText(this, "MainActivity收到事件: " + event.getAction(), 
            Toast.LENGTH_SHORT).show();
    }
}

// 3. 接收事件的Activity
public class DetailActivity extends AppCompatActivity {
    private TextView tvEventInfo;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_detail);
        tvEventInfo = findViewById(R.id.tv_event_info);
    }

    @Override
    protected void onStart() {
        super.onStart();
        EventBus.getDefault().register(this);
    }

    @Override
    protected void onStop() {
        super.onStop();
        EventBus.getDefault().unregister(this);
    }

    // 接收事件并更新UI
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onUserEvent(UserEvent event) {
        if ("UPDATE".equals(event.getAction())) {
            User user = event.getUser();
            tvEventInfo.setText(String.format("EventBus接收:\n用户: %s\n邮箱: %s", 
                user.getName(), user.getEmail()));
        }
    }
}

4.3 依赖配置

// app/build.gradle
dependencies {
    implementation 'org.greenrobot:eventbus:3.3.1'
}

4.4 优缺点分析

优点:

  • 解耦彻底,组件间无引用关系
  • 支持线程切换(ThreadMode)
  • 事件可被多个订阅者接收
  • 适合全局事件通知

缺点:

  • 增加依赖库
  • 事件类型定义需谨慎,避免命名冲突
  • 调试困难(事件流不直观)
  • 可能导致”事件风暴”(过度使用事件总线)

5. 其他通信方式

5.1 静态方法调用(不推荐)

// 不推荐的方式:直接调用静态方法
public class DataHolder {
    private static User currentUser;
    
    public static void setCurrentUser(User user) {
        currentUser = user;
    }
    
    public static User getCurrentUser() {
        return currentUser;
    }
}

// 在Activity中使用
public class MainActivity extends AppCompatActivity {
    private void navigate() {
        // 设置数据
        DataHolder.setCurrentUser(new User(1, "Test", "test@example.com"));
        
        // 跳转
        startActivity(new Intent(this, DetailActivity.class));
    }
}

public class DetailActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 获取数据
        User user = DataHolder.getCurrentUser();
        // 使用数据...
    }
}

问题:内存泄漏风险,无法自动清理,不适合复杂场景。

5.2 单例模式存储

// 单例数据管理器
public class DataManager {
    private static DataManager instance;
    private final Map<String, Object> dataMap = new HashMap<>();
    
    private DataManager() {}
    
    public static DataManager getInstance() {
        if (instance == null) {
            synchronized (DataManager.class) {
                if (instance == null) {
                    instance = new DataManager();
                }
            }
        }
        return instance;
    }
    
    public void putData(String key, Object value) {
        dataMap.put(key, value);
    }
    
    public Object getData(String key) {
        return dataMap.remove(key); // 使用后立即移除,避免内存泄漏
    }
}

注意:必须及时清理数据,否则会导致内存泄漏。

6. 常见错误及处理技巧

6.1 错误1:TransactionTooLargeException(数据传递过大)

问题描述: Android 7.0+限制了Intent传递的数据大小(约1MB),超过限制会抛出TransactionTooLargeException。

解决方案:

// 错误示例:传递大量数据
Intent intent = new Intent(this, DetailActivity.class);
intent.putExtra("LARGE_LIST", (Serializable) largeDataList); // 可能崩溃

// 正确做法1:传递引用ID,通过单例或数据库获取数据
public class DataCache {
    private static final Map<Integer, List<LargeData>> cache = new HashMap<>();
    private static int idCounter = 0;
    
    public static int storeData(List<LargeData> data) {
        int id = idCounter++;
        cache.put(id, data);
        return id;
    }
    
    public static List<LargeData> getData(int id) {
        return cache.remove(id); // 使用后立即清理
    }
}

// 使用
int dataId = DataCache.storeData(largeDataList);
Intent intent = new Intent(this, DetailActivity.class);
intent.putExtra("DATA_ID", dataId);
startActivity(intent);

// 正确做法2:使用文件/数据库存储
// 将数据序列化到文件,传递文件路径

6.2 错误2:内存泄漏(Memory Leak)

问题描述: 在Activity中启动新Activity时,如果持有新Activity的引用或回调,会导致旧Activity无法被回收。

错误示例:

public class MainActivity extends AppCompatActivity {
    private DetailActivity detailActivity; // 错误:持有Activity引用
    
    private void navigate() {
        Intent intent = new Intent(this, DetailActivity.class);
        startActivity(intent);
        // 错误:直接引用会导致内存泄漏
        detailActivity = new DetailActivity(); // 不应该手动创建
    }
}

解决方案:

// 1. 使用弱引用(WeakReference)
public class MainActivity extends AppCompatActivity {
    private WeakReference<DetailActivity> detailActivityRef;
    
    private void navigate() {
        Intent intent = new Intent(this, DetailActivity.class);
        startActivity(intent);
        // 如果必须引用,使用弱引用
        // detailActivityRef = new WeakReference<>(detailActivity);
    }
}

// 2. 更好的做法:使用ViewModel或事件总线,避免直接引用
// 3. 在onDestroy中清理
@Override
protected void onDestroy() {
    super.onDestroy();
    // 清理所有可能泄漏的引用
    detailActivityRef = null;
}

6.3 错误3:NullPointerException(空指针异常)

问题描述: 接收数据时未检查Intent或数据是否为null。

解决方案:

// 错误示例
public class DetailActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 直接使用,可能NPE
        String name = getIntent().getStringExtra("USER_NAME");
        TextView tv = findViewById(R.id.tv_name);
        tv.setText(name); // 如果name为null,显示"null"
    }
}

// 正确做法:防御性编程
public class DetailActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_detail);
        
        Intent intent = getIntent();
        if (intent == null) {
            finish(); // 没有Intent,直接结束
            return;
        }
        
        String name = intent.getStringExtra("USER_NAME");
        if (name == null) {
            name = "默认用户"; // 提供默认值
        }
        
        TextView tv = findViewById(R.id.tv_name);
        if (tv != null) {
            tv.setText(name);
        }
        
        // 或者使用更简洁的方式
        String safeName = Objects.requireNonNullElse(intent.getStringExtra("USER_NAME"), "默认用户");
        tv.setText(safeName);
    }
}

6.4 错误4:ViewModel作用域混淆

问题描述: 在不同Activity中获取ViewModel时,作用域设置错误导致数据不共享。

错误示例:

// MainActivity
SharedViewModel viewModel1 = new ViewModelProvider(this).get(SharedViewModel.class);

// DetailActivity
SharedViewModel viewModel2 = new ViewModelProvider(this).get(SharedViewModel.class);
// 这两个ViewModel实例是不同的!

解决方案:

// 正确做法:使用同一个ViewModelStoreOwner
// 方法1:在Application级别共享(不推荐,可能导致内存泄漏)
public class MyApplication extends Application implements ViewModelStoreOwner {
    private ViewModelStore appViewModelStore;
    
    @Override
    public ViewModelStore getViewModelStore() {
        if (appViewModelStore == null) {
            appViewModelStore = new ViewModelStore();
        }
        return appViewModelStore;
    }
}

// 在Activity中获取
SharedViewModel viewModel = new ViewModelProvider(
    (ViewModelStoreOwner) getApplication()).get(SharedViewModel.class);

// 方法2:使用ActivityResultRegistry(推荐)
public class MainActivity extends AppCompatActivity {
    private final ActivityResultRegistry registry = new ActivityResultRegistry();
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        // 使用ActivityResultLauncher
        ActivityResultLauncher<Intent> launcher = registerForActivityResult(
            new ActivityResultContracts.StartActivityForResult(),
            result -> {
                if (result.getResultCode() == RESULT_OK && result.getData() != null) {
                    // 处理结果
                }
            });
    }
}

6.5 错误5:生命周期不匹配

问题描述: 在Activity的onCreate()中访问尚未初始化的视图或数据。

解决方案:

// 错误示例
public class DetailActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // 错误:在setContentView之前访问视图
        TextView tv = findViewById(R.id.tv_info); // 返回null
        tv.setText("Hello"); // NPE
        
        setContentView(R.layout.activity_detail);
    }
}

// 正确做法
public class DetailActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_detail); // 先设置布局
        
        // 再访问视图
        TextView tv = findViewById(R.id.tv_info);
        if (tv != null) {
            tv.setText("Hello");
        }
        
        // 处理数据
        handleIntentData();
    }
    
    private void handleIntentData() {
        Intent intent = getIntent();
        if (intent == null) return;
        
        // 延迟处理数据,确保视图已初始化
        if (savedInstanceState == null) {
            // 只在首次创建时处理
            processIntentData(intent);
        }
    }
}

6.6 错误6:重复注册监听器

问题描述: 在onCreate()中注册EventBus或LiveData监听器,但未在onDestroy()中注销,导致重复注册和内存泄漏。

解决方案:

// EventBus正确注册/注销
@Override
protected void onStart() {
    super.onStart();
    if (!EventBus.getDefault().isRegistered(this)) {
        EventBus.getDefault().register(this);
    }
}

@Override
protected void onStop() {
    super.onStop();
    if (EventBus.getDefault().isRegistered(this)) {
        EventBus.getDefault().unregister(this);
    }
}

// LiveData正确观察
private void setupObservers() {
    // 在Fragment中使用viewLifecycleOwner
    // 在Activity中使用this
    viewModel.getData().observe(this, data -> {
        // 更新UI
    });
}

// 避免重复观察
private boolean isObserverSetup = false;
private void setupObservers() {
    if (isObserverSetup) return;
    isObserverSetup = true;
    // 设置观察器...
}

6.7 错误7:混淆onActivityResult与新API

问题描述: AndroidX推荐使用ActivityResultLauncher替代startActivityForResult,但开发者仍使用旧API。

解决方案:

// 旧API(已废弃)
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    // 处理结果...
}

// 新API(推荐)
public class MainActivity extends AppCompatActivity {
    // 定义Launcher
    private ActivityResultLauncher<Intent> userSelectLauncher;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        // 注册Launcher
        userSelectLauncher = registerForActivityResult(
            new ActivityResultContracts.StartActivityForResult(),
            result -> {
                if (result.getResultCode() == RESULT_OK && result.getData() != null) {
                    User user = result.getData().getParcelableExtra("SELECTED_USER");
                    if (user != null) {
                        // 更新UI
                        TextView tv = findViewById(R.id.tv_selected_user);
                        tv.setText("选中: " + user.getName());
                    }
                }
            });
        
        Button btnSelect = findViewById(R.id.btn_select);
        btnSelect.setOnClickListener(v -> {
            Intent intent = new Intent(this, UserSelectActivity.class);
            userSelectLauncher.launch(intent);
        });
    }
}

7. 最佳实践总结

7.1 选择策略

  • 简单数据传递:使用Intent + Parcelable
  • 双向通信/结果返回:使用ActivityResultLauncher
  • 多Fragment/Activity共享数据:使用ViewModel + LiveData
  • 全局事件通知:使用EventBus(谨慎使用)
  • 避免:静态变量、单例直接存储Activity引用

7.2 性能优化

// 1. 使用SparseArray替代HashMap(针对整数键)
SparseArray<User> userCache = new SparseArray<>();

// 2. 延迟初始化
private TextView tvInfo;
private TextView getTvInfo() {
    if (tvInfo == null) {
        tvInfo = findViewById(R.id.tv_info);
    }
    return tvInfo;
}

// 3. 使用LruCache缓存对象
private LruCache<Integer, User> userCache = new LruCache<>(100);

// 4. 异步处理大数据
private void processLargeDataAsync(List<LargeData> data) {
    new Thread(() -> {
        // 耗时操作
        List<Result> results = processData(data);
        
        // 回到主线程更新UI
        runOnUiThread(() -> updateUI(results));
    }).start();
}

7.3 安全性考虑

// 1. 数据验证
public class SecureDataTransmitter {
    public static boolean validateUserData(User user) {
        if (user == null) return false;
        if (user.getId() <= 0) return false;
        if (user.getName() == null || user.getName().isEmpty()) return false;
        return true;
    }
}

// 2. 防止Intent注入
public class SafeActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        Intent intent = getIntent();
        if (intent != null && intent.getData() != null) {
            // 验证URI来源
            Uri data = intent.getData();
            if (!isValidUri(data)) {
                finish();
                return;
            }
        }
    }
    
    private boolean isValidUri(Uri uri) {
        // 检查URI是否来自可信来源
        return "com.yourapp".equals(uri.getHost());
    }
}

7.4 调试技巧

// 1. 添加日志追踪数据流
public class DebugDataTransmitter {
    private static final String TAG = "DataFlow";
    
    public static void logDataTransfer(String from, String to, Object data) {
        Log.d(TAG, String.format("Transfer: %s -> %s, Data: %s", 
            from, to, data != null ? data.getClass().getSimpleName() : "null"));
    }
}

// 2. 使用StrictMode检测问题
public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        
        if (BuildConfig.DEBUG) {
            StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                .detectAll()
                .penaltyLog()
                .build());
            
            StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                .detectAll()
                .penaltyLog()
                .build());
        }
    }
}

8. 总结

跨Activity通信是Android开发的核心技能,选择合适的方案取决于具体场景:

  1. Intent传递:适合简单、一次性数据传递
  2. ActivityResultLauncher:适合需要返回结果的交互场景
  3. ViewModel:现代推荐方式,适合共享数据和配置更改
  4. EventBus:适合解耦的全局事件,但需谨慎使用

关键原则:

  • 避免直接引用Activity实例
  • 及时清理资源,防止内存泄漏
  • 做好空值检查和异常处理
  • 遵循Android生命周期规范
  • 优先使用AndroidX推荐的新API

通过合理选择通信方式并遵循最佳实践,可以构建出健壮、高效、可维护的Android应用。