You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Android Studio中自定义实现观察者模式,将Activity作为被观察者

核心问题澄清
  • 绝对不要手动创建Activity实例:Android四大组件的实例均由系统负责创建与生命周期调度,自行new出的MainActivity没有和系统上下文绑定,属于完全无效的空对象,会直接引发崩溃、内存泄漏等问题,该实现思路不可行。
  • Activity可以作为被观察者,但需要严格遵守Android生命周期规则,观察者必须在对应生命周期主动完成订阅/取消订阅操作,避免持有已经销毁的Activity引用。如果你的场景需要跨多个Activity分发事件,更推荐将被观察者抽为全局单例管理类,和具体Activity解耦,不受单个页面生命周期影响。
最简观察者模式实现方案

步骤1:定义基础接口

首先定义观察者和被观察者的通用接口:

// 观察者接口
public interface UrlObserver {
    void onUrlGenerated(String url);
}
// 被观察者接口
public interface UrlSubject {
    void registerObserver(UrlObserver observer);
    void removeObserver(UrlObserver observer);
    void notifyObservers(String url);
}

步骤2:实现全局单例被观察者

将事件分发逻辑抽为单例管理类,避免和具体页面耦合:

public class UrlEventManager implements UrlSubject {
    private static volatile UrlEventManager INSTANCE;
    private final List<UrlObserver> observerList = new ArrayList<>();

    private UrlEventManager() {}

    public static UrlEventManager getInstance() {
        if (INSTANCE == null) {
            synchronized (UrlEventManager.class) {
                if (INSTANCE == null) {
                    INSTANCE = new UrlEventManager();
                }
            }
        }
        return INSTANCE;
    }

    @Override
    public void registerObserver(UrlObserver observer) {
        if (!observerList.contains(observer)) {
            observerList.add(observer);
        }
    }

    @Override
    public void removeObserver(UrlObserver observer) {
        observerList.remove(observer);
    }

    @Override
    public void notifyObservers(String url) {
        for (UrlObserver observer : observerList) {
            observer.onUrlGenerated(url);
        }
    }
}

步骤3:MainActivity触发事件

用户点击按钮生成URL后,直接调用单例类完成事件分发:

public class MainActivity extends AppCompatActivity {
    private EditText inputEt;
    private Button jumpBtn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        inputEt = findViewById(R.id.input_et);
        jumpBtn = findViewById(R.id.jump_btn);
        
        jumpBtn.setOnClickListener(v -> {
            String inputContent = inputEt.getText().toString().trim();
            // 自定义生成URL的逻辑
            String generatedUrl = "https://example.com/?content=" + Uri.encode(inputContent);
            // 分发事件给所有观察者
            UrlEventManager.getInstance().notifyObservers(generatedUrl);
            // 跳转到Activity1
            startActivity(new Intent(this, Activity1.class));
        });
    }
}

步骤4:观察者页面实现订阅

以Activity1为例,所有需要接收URL的页面都实现UrlObserver接口,同时在生命周期中完成订阅和取消订阅操作:

public class Activity1 extends AppCompatActivity implements UrlObserver {
    private TextView showUrlTv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_1);
        showUrlTv = findViewById(R.id.show_url_tv);
    }

    @Override
    protected void onStart() {
        super.onStart();
        // 订阅事件
        UrlEventManager.getInstance().registerObserver(this);
    }

    @Override
    protected void onStop() {
        super.onStop();
        // 必须取消订阅,避免内存泄漏
        UrlEventManager.getInstance().removeObserver(this);
    }

    @Override
    public void onUrlGenerated(String url) {
        // 更新UI展示URL
        showUrlTv.setText(url);
    }
}
注意事项
  • 如果你的场景仅需要跳转时传递一次数据,直接使用Intent.putExtra()传递参数更简单,观察者模式更适合多订阅端、多频次事件更新的场景
  • 所有观察者必须在页面销毁前主动取消订阅,避免内存泄漏
  • 不要自行创建任何Android组件的实例,所有组件的生命周期都由系统统一调度

内容的提问来源于stack exchange,提问作者MUCHUAN SU

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 01:54:01