Android(Kotlin)中React Native跨Activity传递Promise问题求助
解决方案:在React Native原生模块中启动Activity并传递Promise处理异步结果
嘿,作为刚上手Android的RN开发者,遇到这种原生模块里要启动Activity并关联Promise的需求很正常~其实核心思路是没法直接把Promise对象通过Intent传递,所以我们用「唯一ID + 全局存储」的方式来关联Promise和Activity,下面给你一步步拆解实现:
1. 在原生模块中创建Promise存储容器
首先在你的ReactNativeBridge类里,定义一个全局的Map来存Promise,用唯一ID作为key。因为可能涉及多线程操作,建议用ConcurrentHashMap保证线程安全:
import com.facebook.react.bridge.Promise; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactMethod; import android.content.Intent; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; public class ReactNativeBridge extends ReactContextBaseJavaModule { // 全局存储Promise,key是唯一ID private final ConcurrentHashMap<String, Promise> promiseMap = new ConcurrentHashMap<>(); private static ReactApplicationContext reactContext; public ReactNativeBridge(ReactApplicationContext context) { super(context); reactContext = context; } @Override public String getName() { return "ReactNativeBridge"; } // 对外暴露的获取Promise的方法,供Activity调用 public static Promise getPromise(String promiseId) { return promiseMap.get(promiseId); } // 移除已处理的Promise,避免内存泄漏 public static void removePromise(String promiseId) { promiseMap.remove(promiseId); } }
2. 在@ReactMethod方法中启动Activity并传递Promise ID
接下来,在你需要启动Activity的@ReactMethod方法里,生成唯一ID,把Promise存入Map,然后通过Intent把ID传给目标Activity:
@ReactMethod public void startTargetActivity(Promise promise) { // 生成唯一ID String promiseId = UUID.randomUUID().toString(); // 存储Promise promiseMap.put(promiseId, promise); // 启动目标Activity,传递Promise ID Intent intent = new Intent(getReactApplicationContext(), TargetActivity.class); intent.putExtra("PROMISE_ID", promiseId); // 注意:如果是在非Activity环境启动,需要添加FLAG_ACTIVITY_NEW_TASK intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); getReactApplicationContext().startActivity(intent); }
3. 在目标Activity中处理任务并回调Promise
在TargetActivity里,拿到传递过来的Promise ID,完成业务逻辑后,通过ReactNativeBridge的静态方法获取对应的Promise,然后执行resolve或reject,最后记得移除Promise:
import android.os.Bundle; import androidx.appcompat.app.AppCompatActivity; import com.facebook.react.bridge.Promise; import android.view.View; public class TargetActivity extends AppCompatActivity { private String promiseId; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_target); // 获取传递过来的Promise ID promiseId = getIntent().getStringExtra("PROMISE_ID"); // 模拟任务成功场景 findViewById(R.id.btn_success).setOnClickListener(v -> { Promise promise = ReactNativeBridge.getPromise(promiseId); if (promise != null) { promise.resolve("Activity任务执行成功!"); ReactNativeBridge.removePromise(promiseId); } finish(); }); // 模拟任务失败场景 findViewById(R.id.btn_fail).setOnClickListener(v -> { Promise promise = ReactNativeBridge.getPromise(promiseId); if (promise != null) { promise.reject("TASK_FAILED", "Activity任务执行出错"); ReactNativeBridge.removePromise(promiseId); } finish(); }); } // 处理Activity意外销毁的情况,避免Promise一直挂着导致内存泄漏 @Override protected void onDestroy() { super.onDestroy(); Promise promise = ReactNativeBridge.getPromise(promiseId); if (promise != null && !promise.isResolved() && !promise.isRejected()) { promise.reject("ACTIVITY_CANCELLED", "Activity被销毁,任务取消"); ReactNativeBridge.removePromise(promiseId); } } }
4. React Native端调用示例
最后在RN端调用这个原生方法,用async/await处理Promise结果:
import { NativeModules } from 'react-native'; const { ReactNativeBridge } = NativeModules; // 调用原生方法启动Activity const startNativeActivity = async () => { try { const result = await ReactNativeBridge.startTargetActivity(); console.log('原生返回结果:', result); } catch (error) { console.error('原生调用出错:', error); } };
关键注意事项
- 内存泄漏防范:一定要在Promise处理完成(或者Activity销毁)后,从Map中移除对应的Promise,不然会导致内存泄漏。
- 线程安全:用
ConcurrentHashMap存储Promise,避免多线程操作时的并发问题。 - Activity启动标记:如果是在非Activity的上下文(比如原生模块)中启动Activity,必须添加
FLAG_ACTIVITY_NEW_TASK标记,否则会抛出异常。
内容的提问来源于stack exchange,提问作者Pranit Harekar
相关产品推荐
相关产品推荐

