【问题标题】:How to implement observer pattern in android studio?如何在android studio中实现观察者模式?
【发布时间】:2022-01-01 07:02:21
【问题描述】:

阅读Headfirst 设计模式后,我想知道在我的应用中实现观察者设计模式的最简单方法。

上下文:

在app的MainActivity中,用户在EditTextView中输入并点击按钮后,会生成一个URL并发送给其他Activity进行展示。 (也切换到其他活动1)

我想让我的 MainACtivity 作为 Subject(Observable) 和 Activity1 和 Activity 2 作为我的观察者。

我没有使用内置的观察者接口,而是尝试使用自定义的观察者和主题接口来实现这种模式(就像他们在书中所做的那样)。

但是这种方式包括在 Observer 类中创建一个 Subject 实例,这意味着我将在我的其他 Observer 类中创建一个 MainActivity 实例,我不确定它是否有效,谁能告诉我如何正确地做到这一点? (或者我只是不能将活动用作主题?)

【问题讨论】:

    标签: java android android-activity observer-pattern


    【解决方案1】:

    您无法在不同的活动中观察对象。您所能做的就是使用 Intents 在 Activity 之间传递数据。

    在 Android 中,观察者模式是通过使用 ViewModel 类和 LiveData / StateFlow 类来实现的。如果您想要 3 个不同的屏幕来观察单个对象的变化。您需要有 3 个 Fragment 共享相同的 Activity 和相同的 ViewModel。

    public class SharedViewModel extends ViewModel {
        private final MutableLiveData<Item> selected = new MutableLiveData<Item>();
    
        public void select(Item item) {
           selected.setValue(item);
        }
    
        public LiveData<Item> getSelected() {
            return selected;
         }
    }
    

    此处的 LiveData 是您通过所选变量间接更新的主题。可以通过从 Fragment 调用 select() 函数来更改所选变量。在每个 Fragment 中,您必须创建 ViewModel 并观察 LiveData。

    public class ListFragment extends Fragment {
        private SharedViewModel model;
    
        public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
           super.onViewCreated(view, savedInstanceState);
           model = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
           itemSelector.setOnClickListener(item -> {
               model.select(item);
           });
           model.getSelected().observe(getViewLifecycleOwner(), item -> {
               // Update the UI.
            });
    
         }
    }
    

    您可以在此处阅读有关上述示例的更多信息:https://developer.android.com/topic/libraries/architecture/viewmodel#java

    此解决方案也更可取,因为 ViewModel 在配置更改后仍然存在,并且即使在 Activity 被销毁后也可以恢复您的 Activity 状态。

    此外,您不应在另一个 Activity 或 ViewModel 中保留对一个 Activity 的任何引用,因为这可能导致内存泄漏。

    如果您找到了用例,您可以尝试在同一活动或 ViewModel 中的对象之间创建自己的观察者模式,但在大多数情况下,LiveData 和 StateFlow 应该足以更新您的 UI。

    【讨论】:

    • 听起来我可以很容易地使用 sharedViewModel 来实现这一点,我想知道它是否是一种观察者模式?它看起来与一个非常相似。
    • 没错,就是观察者模式。在观察者模式中,主体不知道观察者收到有关数据更改的通知,而这正是 ViewModel 中发生的情况。 LiveData 或 ViewModel 不跟踪观察数据的任何 Fragment 或活动。 ViewModel 只保存 LiveData 变量,LiveData 允许任何人观察它以获取更新。
    【解决方案2】:

    任何特定的 Activity 实例都是短暂的视图持有者。我说短暂是因为 Android 会为任何配置更改(如屏幕旋转)销毁并重新创建它。这就是为什么在不同活动之间传递引用并非易事的原因。它还会导致内存泄漏绕过 Activity 实例。将 Activity 用作可观察对象是不可行的。

    您可以做的是让您的 MainActivity 将更改发布到某个存储库类,并让该存储库类公开其他活动可以查看的 observable。在这种情况下,存储库必须具有应用程序范围。它可以在您的应用程序类中延迟创建并从应用程序中检索。如果您使用的是依赖注入框架,则存储库将是应用程序范围的单例。

    Activity 或 Fragment 与存储库交互的常见模式是通过 ViewModel 类。

    【讨论】:

    • 在这种情况下,这是否意味着存储库类将成为我的主题类?
    • 现在在阅读了 Viewmodel 之后,我认为 ViewModel 类是包含让我观察主题和从主题获得的数据的方法的类?
    • 有点像观察者模式,存储库作为主体,活动/片段作为观察者,但 ViewModel 在它们之间充当中介。 ViewModel 中的 LiveData 是对观察者的弱引用。存在 ViewModel 的原因是它允许一个类可以保持状态,即使在配置更改期间 Activity 被销毁和重新创建时也是如此。您可以省略 ViewModel 并直接从存储库中公开 LiveData,但这会使您的业务逻辑和 UI 更紧密地耦合,这可能会使单元测试更加困难。
    猜你喜欢
    • 2011-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-09
    • 1970-01-01
    • 2017-05-04
    • 1970-01-01
    相关资源
    最近更新 更多