
本文介绍在 android 中通过接口回调机制,让非 ui 线程(如 http 请求线程)安全、解耦地通知 mainactivity 并启动新 activity,避免直接持有 activity 引用导致内存泄漏或崩溃。
本文介绍在 android 中通过接口回调机制,让非 ui 线程(如 http 请求线程)安全、解耦地通知 mainactivity 并启动新 activity,避免直接持有 activity 引用导致内存泄漏或崩溃。
在 Android 开发中,从子线程(例如 Runnable 或 Thread 内部)直接操作 UI 组件(如启动 Activity、更新 TextView)是非法的,且直接持有 MainActivity 的强引用极易引发内存泄漏或 Activity has been destroyed 异常。因此,不推荐将 Handler、Context 或 Activity 实例直接传入后台任务类;更优解是采用面向接口的回调设计(Callback Pattern),实现线程间通信的松耦合与生命周期安全。
✅ 推荐方案:定义并实现回调接口
首先,在独立的网络请求类(如 HttpRequestTask)中声明一个回调接口,并通过构造函数注入回调实例:
// HttpRequestTask.java
public class HttpRequestTask {
private final Callback callback;
public interface Callback {
void onResponseReceived(Intent intent); // 支持携带数据启动 Activity
void onError(String message);
}
public HttpRequestTask(Callback callback) {
this.callback = callback;
}
public void execute() {
new Thread(() -> {
try {
// 模拟网络请求(实际建议使用 OkHttp/Retrofit + Call.enqueue)
Thread.sleep(2000);
Intent intent = new Intent();
intent.setClass(null, SecondActivity.class); // 注意:此处不能传 null Context,见下方说明
// ✅ 正确做法:由 MainActivity 构造 Intent 并传入
callback.onResponseReceived(intent);
} catch (Exception e) {
callback.onError(e.getMessage());
}
}).start();
}
}⚠️ 注意:Intent 的构造必须在主线程完成,且需关联有效的 Context。因此,不要在子线程中调用 new Intent(MainActivity.this, ...) —— MainActivity.this 在子线程中不可用,且 Activity 可能已被销毁。正确做法是:回调仅传递必要数据(如状态码、JSON 字符串),由 MainActivity 在主线程中创建并启动 Intent。
在 MainActivity 中实现该接口,并确保回调在主线程执行(Android UI 操作必须在主线程):
// MainActivity.java
public class MainActivity extends AppCompatActivity implements HttpRequestTask.Callback {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btn_request).setOnClickListener(v -> {
// 创建任务并传入当前 Activity 作为回调接收者
HttpRequestTask task = new HttpRequestTask(this);
task.execute();
});
}
@Override
public void onResponseReceived(Intent intent) {
// ✅ 安全:运行在主线程,可安全操作 UI
Intent launchIntent = new Intent(this, SecondActivity.class);
// 可附加数据:launchIntent.putExtra("result", data);
startActivity(launchIntent);
}
@Override
public void onError(String message) {
// 使用 Toast 或 Snackbar 提示错误(同样需在主线程)
runOnUiThread(() ->
Toast.makeText(this, "Request failed: " + message, Toast.LENGTH_SHORT).show()
);
}
// ? 生命周期防护:防止回调在 Activity 销毁后执行(可选但强烈推荐)
@Override
protected void onDestroy() {
super.onDestroy();
// 若任务支持取消,此处可调用 task.cancel()
}
}✅ 关键优势与注意事项
- 解耦清晰:HttpRequestTask 不依赖任何 Android 组件,便于单元测试和复用;
- 线程安全:所有 UI 操作(startActivity、Toast)均在主线程完成,规避 CalledFromWrongThreadException;
- 内存安全:未持有 Activity 强引用(接口本身不持有上下文),避免常见内存泄漏;
- 生命周期感知:建议在 onDestroy() 中清理未完成任务(如配合 AtomicBoolean isCancelled);
- 现代替代方案提示:在新项目中,更推荐使用 ViewModel + LiveData/StateFlow,或协程 lifecycleScope.launch 配合 withContext(Dispatchers.IO),进一步简化异步流程。
综上,接口回调是轻量、可靠、符合 Android 最佳实践的跨线程通信方式。它既规避了 Handler 易误用的风险,又比 BroadcastReceiver 更高效直接,是处理“后台任务完成 → 启动新界面”场景的首选方案。










