Java 中的 Android 架构 SingleLiveEvent 和 EventObserver 实践示例

And*_*Man 8 java android android-architecture-components

我尝试使用两个字段 ( username, password)制作示例登录页面,并使用 android 架构组件保存按钮,使用 android 数据绑定,验证viewmodel视图模型中和来自视图模型的数据我调用存储库以进行远程服务器调用,如官方文档,远程服务器中所述成功返回用户 ID 那么如何使用此成功从视图模型开始新片段?我学到了一些关于singleLiveEventand 的知识EventObserver,但我找不到明确的用法示例:

登录视图模型

private MutableLiveData<String> snackbarStringSingleLiveEvent= new MutableLiveData<>();

@Inject
public LoginViewModel(@NonNull AppDatabase appDatabase, 
                      @NonNull JobPortalApplication application,
                      @NonNull MyApiEndpointInterface myApiEndpointInterface) {
    super(application);
    loginRepository = new LoginRepository(application, appDatabase, myApiEndpointInterface);
    snackbarStringSingleLiveEvent = loginRepository.getLogin(username.get(), password.get(), type.get());
}

public MutableLiveData<String> getSnackbarStringSingleLiveEvent() {
    return snackbarStringSingleLiveEvent;
}
Run Code Online (Sandbox Code Playgroud)

存储库

public SingleLiveEvent<String> getLogin(String name, String password, String type) {
    SingleLiveEvent<String> mutableLiveData = new SingleLiveEvent<>();
    
    apiEndpointInterface.getlogin(name, password, type).enqueue(new Callback<GenericResponse>() {
        @Override
        public void onResponse(Call<GenericResponse> call, Response<GenericResponse> response) {
            mutableLiveData.setValue(response.body().getMessage());
        }

        @Override
        public void onFailure(Call<GenericResponse> responseCall, Throwable t) {
            mutableLiveData.setValue(Constant.FAILED);
        }
    });

    return mutableLiveData;
}
Run Code Online (Sandbox Code Playgroud)

登录片段

private void observeViewModel(final LoginViewModel viewModel) {
    // Observe project data
    viewModel.getSnackbarStringSingleLiveEvent().observe(this, new Observer<String>() {
        @Override
        public void onChanged(String s) {
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

EventObserver在上述情况下如何使用?有什么实际例子吗?

Jee*_*ede 7

查看以下示例,了解如何创建单个 LiveEvent以仅观察一次LiveData

创建一个Event如下所示的类,它将提供我们的数据一次并充当LiveDatawrapper 的子项:

public class Event<T> {
    private boolean hasBeenHandled = false;
    private T content;

    public Event(T content) {
        this.content = content;
    }

    public T getContentIfNotHandled() {
        if (hasBeenHandled) {
            return null;
        } else {
            hasBeenHandled = true;
            return content;
        }
    }

    public boolean isHandled() {
        return hasBeenHandled;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后EventObserver像下面这样声明这个类,这样我们就不会Event每次、任何地方都放置检查处理的条件

public class EventObserver<T> implements Observer<Event<T>> {
    private OnEventChanged onEventChanged;

    public EventObserver(OnEventChanged onEventChanged) {
        this.onEventChanged = onEventChanged;
    }

    @Override
    public void onChanged(@Nullable Event<T> tEvent) {
        if (tEvent != null && tEvent.getContentIfNotHandled() != null && onEventChanged != null)
            onEventChanged.onUnhandledContent(tEvent.getContentIfNotHandled());
    }

    interface OnEventChanged<T> {
        void onUnhandledContent(T data);
    }
}
Run Code Online (Sandbox Code Playgroud)

以及如何实现它:

MutableLiveData<Event<String>> data = new MutableLiveData<>();

// And observe like below
data.observe(lifecycleOwner, new EventObserver<String>(data -> {
        // your unhandled data would be here for one time.
    }));

// And this is how you add data as event to LiveData
data.setValue(new Event(""));
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅此处


OP编辑:

是的,data.setValue(new Event(""));当您从 API 得到响应时用于存储库(请记住返回LiveData您在 VM 中采用的相同类型,而不是SingleLiveEvent类)

所以,让我们说你已经创建LiveDataViewModel象下面这样:

private MutableLiveData<Event<String>> snackbarStringSingleLiveEvent= new MutableLiveData<>();
Run Code Online (Sandbox Code Playgroud)

您将此实时数据作为来自存储库的单个事件提供价值,如下所示:

@Override
public void onResponse(Call<GenericResponse> call, Response<GenericResponse> response) {
    mutableLiveData.setValue(new Event(response.body().getMessage())); // we set it as Event wrapper class.
}
Run Code Online (Sandbox Code Playgroud)

并在 UI (Fragment)上观察它,如下所示:

viewModel.getSnackbarStringSingleLiveEvent().observe(this, new EventObserver<String>(data -> {
        // your unhandled data would be here for one time.
    }));
Run Code Online (Sandbox Code Playgroud)