如何判断Activity是否活跃并在活跃时传递Service数据至Activity
1. 实现HomeActivity活跃状态校验
不要在Service中直接持有Activity引用判断状态,会引发内存泄漏,通过Application级别的生命周期监听+静态标记位实现即可,无内存泄漏风险。
首先自定义Application类,注册Activity生命周期回调:
public class App extends Application { // 全局标记HomeActivity是否处于前台活跃状态 public static boolean isHomeActive = false; @Override public void onCreate() { super.onCreate(); registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacks() { @Override public void onActivityResumed(@NonNull Activity activity) { if (activity instanceof HomeActivity) { isHomeActive = true; } } @Override public void onActivityPaused(@NonNull Activity activity) { if (activity instanceof HomeActivity) { isHomeActive = false; } } // 其余生命周期方法空实现即可 @Override public void onActivityCreated(@NonNull Activity a, @Nullable Bundle b) {} @Override public void onActivityStarted(@NonNull Activity a) {} @Override public void onActivityStopped(@NonNull Activity a) {} @Override public void onActivitySaveInstanceState(@NonNull Activity a, @NonNull Bundle b) {} @Override public void onActivityDestroyed(@NonNull Activity a) {} }); } }
记得在AndroidManifest.xml中把Application的name属性配置为上述自定义的App类,否则生命周期监听不生效。
之后在EventReceivingService中补全原有的状态判断方法即可:
private boolean isActivityActive() { return App.isHomeActive; }
注意:你原有代码中判断条件写的
isACtive存在拼写错误,需要修正为isActive,否则会出现编译错误。
2. 活跃状态下直接向HomeActivity传递数据
用本地广播实现Service到Activity的通信即可,不会有内存泄漏问题,也不需要做跨进程适配。
首先在EventReceivingService中实现passData方法:
private void passData(JSONData data) { Intent intent = new Intent("com.yourapp.ACTION_NEW_DATA"); // JSON数据直接转字符串传递即可 intent.putExtra("data_json", data.toString()); LocalBroadcastManager.getInstance(this).sendBroadcast(intent); }
之后在HomeActivity中注册对应广播接收器,收到数据后直接更新UI,注意要在对应生命周期注册和注销接收器:
private final BroadcastReceiver newDataReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String jsonStr = intent.getStringExtra("data_json"); try { JSONData data = new JSONData(jsonStr); renderUI(data); // 替换为你自己的UI更新逻辑 } catch (JSONException e) { e.printStackTrace(); } } }; @Override protected void onResume() { super.onResume(); IntentFilter filter = new IntentFilter("com.yourapp.ACTION_NEW_DATA"); LocalBroadcastManager.getInstance(this).registerReceiver(newDataReceiver, filter); } @Override protected void onPause() { super.onPause(); LocalBroadcastManager.getInstance(this).unregisterReceiver(newDataReceiver); }
如果项目接入了Jetpack组件,也可以用全局单例的MutableLiveData<JSONData>替代本地广播,不需要手动注册注销接收器,代码会更简洁。
3. 非活跃状态下缓存数据
单条JSON数据缓存用SharedPreferences足够,不需要引入数据库增加复杂度,存储时直接覆盖旧数据,保证读取时永远是最新内容:
private void storeData(JSONData data) { SharedPreferences sp = getSharedPreferences("data_cache", MODE_PRIVATE); sp.edit().putString("latest_unconsumed_data", data.toString()).apply(); }
4. Activity恢复活跃时读取缓存数据
在HomeActivity的onResume方法中,注册完广播之后主动检查一次缓存,如果存在未消费的缓存数据,直接读取使用,消费完成后清空缓存避免重复展示:
@Override protected void onResume() { super.onResume(); IntentFilter filter = new IntentFilter("com.yourapp.ACTION_NEW_DATA"); LocalBroadcastManager.getInstance(this).registerReceiver(newDataReceiver, filter); // 读取缓存数据 SharedPreferences sp = getSharedPreferences("data_cache", MODE_PRIVATE); String cacheJson = sp.getString("latest_unconsumed_data", null); if (cacheJson != null) { try { JSONData cacheData = new JSONData(cacheJson); renderUI(cacheData); // 消费完成删除缓存 sp.edit().remove("latest_unconsumed_data").apply(); } catch (JSONException e) { e.printStackTrace(); } } }
如果后续需要缓存多条数据排队消费,把SharedPreferences替换为Room数据库或者本地JSON文件队列即可,核心判断逻辑不需要改动。
内容的提问来源于stack exchange,提问作者Albert Einstien

