Архитектура Android Пример SingleLiveEvent и EventObserver в Java - PullRequest
0 голосов
/ 10 мая 2019

Я пытаюсь создать пример страницы входа в систему с двумя полями (username, password) и кнопку сохранения с компонентом архитектуры Android, используя привязку данных Android, проверяя данные в viewmodel, и из модели представления я вызываю репозиторий для удаленного сервера. вызовите, как указано в официальном документе, удаленный сервер вернет мне идентификатор пользователя с успехом, так как я могу запустить новый фрагмент из модели представления, используя этот успех? Я узнал кое-что о singleLiveEvent и EventObserver, но не смог найти там четкого примера использования:

LoginViewModel

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;
}

Хранилище

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;
}

Фрагмент входа в систему

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

Как я могу использовать EventObserver в вышеуказанном случае? Есть практический пример?

Ответы [ 2 ]

0 голосов
/ 10 мая 2019

Event.java

public class Event<T> {

  private T content;

  private boolean hasBeenHandled = false;

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

  /**
   * Returns the content and prevents its use again.
   */
  public T getContentIfNotHandled() {
      if (hasBeenHandled) {
          return null;
      } else {
          hasBeenHandled = true;
          return content;
      }
  }

  /**
   * Returns the content, even if it's already been handled.
   */
  public T peekContent() {
      return content;
  }
}

EventObserver.java

public class EventObserver<T> implements Observer<Event<? extends T>> {

   public interface EventUnhandledContent<T> {
       void onEventUnhandledContent(T t);
   }

   private EventUnhandledContent<T> content;

   public EventObserver(EventUnhandledContent<T> content) {
       this.content = content;
   }

   @Override
   public void onChanged(Event<? extends T> event) {
       if (event != null) {
           T result = event.getContentIfNotHandled();
           if (result != null && content != null) {
               content.onEventUnhandledContent(result);
           }
       }
   }
}

Пример, в классе ViewModel

public class LoginViewModel extends BaseViewModel {
   private MutableLiveData<Event<Boolean>> _isProgressEnabled = new MutableLiveData<>();
   LiveData<Event<Boolean>> isProgressEnabled = _isProgressEnabled;

   private AppService appService;

   private SchedulerProvider schedulerProvider;

   private SharedPreferences preferences;

  @Inject
  LoginViewModel(
          AppService appService,
          SchedulerProvider schedulerProvider,
          SharedPreferences preferences
  ) {
      this.appService = appService;
      this.schedulerProvider = schedulerProvider;
      this.preferences = preferences;
    }


   public void login(){
   appService.login("username", "password")
                          .subscribeOn(schedulerProvider.executorIo())
                          .observeOn(schedulerProvider.ui())
                          .subscribe(_userLoginDetails::setValue,
                                     _userLoginDetailsError::setValue,
                                     () -> _isProgressEnabled.setValue(new Event<>(false)),
                                     d -> _isProgressEnabled.setValue(new Event<>(true))
                          )
   }
}

В Фрагменте логина,

viewModel.isProgressEnabled.observe(this, new EventObserver<>(hasEnabled -> {
        if (hasEnabled) {
            // showProgress
        } else {
            // hideProgress
        }
    }));

Используя классы Event и EventObserver, мы можем достичь того же, что и класс SingleLiveEvent, но если вы думаете о большом количестве стандартного кода, просто избегайте этого метода. Я надеюсь, что это поможет вам и даст некоторое представление о том, почему мы используем SingleEvent в LiveData.

0 голосов
/ 10 мая 2019

Посмотрите ниже пример того, как вы можете создать один LiveEvent , чтобы наблюдать только один раз как LiveData:

Создать класс с именем Event какниже это предоставит наши данные один раз и будет действовать как потомок LiveData оболочки:

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;
    }
}

Затем объявите этот класс 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);
    }
}

И как вы можете это реализовать:

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(""));

См. здесь для подробностей.


Редактировать для OP :

Да, data.setValue(new Event("")); предназначено для хранилища, когда вы получили ответ от API (не забудьте вернуть тот же LiveData тип, который вы использовали в ВМ вместо SingleLiveEvent класса) .

Итак, допустим, вы создали LiveDataв ViewModel, как показано ниже:

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

Вы указываете значение этого вивата в виде Одиночное событие из репозитория, как показано ниже:

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

И соблюдайте егоn UI (фрагмент) как показано ниже:

viewModel.getSnackbarStringSingleLiveEvent().observe(this, new EventObserver<String>(data -> {
        // your unhandled data would be here for one time.
    }));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...