如何将实现接口的Activity弱引用传递给单例类?
正确实现接收IAnalytics弱引用的单例类
首先,先确认你的基础接口定义没问题:
public interface IAnalytics { String getAnalyticViewName(); }
接下来我会帮你完善AnalyticsWrapper单例类的实现,既要保证单例的唯一性,又能安全持有所有实现IAnalytics接口的Activity弱引用,同时避免内存泄漏:
public class AnalyticsWrapper { // 用volatile保证多线程下实例的可见性 private static volatile AnalyticsWrapper instance; // 持有IAnalytics的弱引用,避免Activity泄漏 private WeakReference<IAnalytics> analyticsWeakRef; // 私有构造,禁止外部直接实例化 private AnalyticsWrapper() {} // 无参版getInstance,用于获取全局唯一实例 public static AnalyticsWrapper getInstance() { // 双重检查锁实现线程安全的单例 if (instance == null) { synchronized (AnalyticsWrapper.class) { if (instance == null) { instance = new AnalyticsWrapper(); } } } return instance; } // 带参版getInstance,用于更新当前的IAnalytics弱引用 public static AnalyticsWrapper getInstance(WeakReference<IAnalytics> analyticsRef) { AnalyticsWrapper wrapper = getInstance(); // 更新弱引用,确保单例始终持有最新的Activity引用 wrapper.analyticsWeakRef = analyticsRef; return wrapper; } // 提供安全获取当前IAnalytics实例的方法(必须判空) public IAnalytics getCurrentAnalytics() { return analyticsWeakRef != null ? analyticsWeakRef.get() : null; } // 示例:封装统计逻辑,自动获取当前页面名称 public void trackPageView() { IAnalytics analytics = getCurrentAnalytics(); if (analytics != null) { String viewName = analytics.getAnalyticViewName(); // 这里替换成你的实际统计代码,比如上报到统计平台 // Log.d("Analytics", "上报页面:" + viewName); } } // 可选:提供手动清空引用的方法,更安全 public void clearAnalyticsRef() { this.analyticsWeakRef = null; } }
关键细节说明
- 线程安全的单例:用双重检查锁+
volatile修饰符,确保多线程环境下不会创建多个实例,同时避免指令重排导致的半初始化问题。 - 弱引用的安全使用:每次获取
IAnalytics实例时都要判空,因为弱引用会在Activity被GC回收时自动释放,防止空指针异常。 - 灵活更新引用:分离无参和带参的
getInstance方法,既保证单例全局唯一,又能在Activity生命周期合适的时机更新引用。
Activity中的调用方式
因为所有Activity都实现了IAnalytics,建议你创建一个基类Activity,统一处理引用的更新和清空:
public class BaseAnalyticsActivity extends AppCompatActivity implements IAnalytics { @Override protected void onResume() { super.onResume(); // 当Activity回到前台时,更新单例的弱引用 AnalyticsWrapper.getInstance(new WeakReference<>(this)); } @Override protected void onPause() { super.onPause(); // 当Activity退到后台时,清空引用(可选,但更安全) AnalyticsWrapper.getInstance().clearAnalyticsRef(); } // 子类需要实现这个方法,返回当前页面的统计名称 @Override public String getAnalyticViewName() { return this.getClass().getSimpleName(); } }
这样所有继承BaseAnalyticsActivity的页面都会自动维护单例中的引用,你在任何地方调用AnalyticsWrapper.getInstance().trackPageView()就能自动获取当前页面的名称进行统计了。
内容的提问来源于stack exchange,提问作者dev90
相关产品推荐
相关产品推荐

