#android #networking #interface #callback #retrofit
#Android #сеть #интерфейс #обратный вызов #модернизация
Вопрос:
Я получаю обратные вызовы из сетевых запросов через интерфейсы.
Предположим, что есть два класса, A amp; B. Класс A инициирует все сетевые запросы, которые выполняются B. Когда B завершает задачу, он должен ответить на A.
Я делаю это так:
public interface MyCallback {
void onTaskDone(String successMessage);
void onTaskFailed(String failMessage);
}
public class A {
onCreate() {
B objectB = new B();
objectB.loginUser(username, password, new MyCallback {
void onTaskDone(successmessage) {
//this is called when task is successful
}
void onTaskFailed(failMessage) {
//this is called when task is failed
});
}
}
}
public class B {
public void loginUser(String username, String password, MyCallback callback) {
//after task is performed
if (task.isSuccessful()) {
callback.onTaskDone("Successful");
} else {
callback.onTaskFailed("Programming is fun they said...");
}
}
}
Как вы можете видеть, если задача выполнена успешно, методы интерфейса вызываются из B, который получен в A.
В чем мой вопрос: существуют ли лучшие способы получения обратных вызовов помимо использования интерфейсов, или этот метод можно улучшить? Одна из проблем, с которой я сталкиваюсь при реализации этого метода, заключается в том, что я использую один и тот же интерфейс со многими методами. В конкретном случае используется только один или два метода, в то время как остальные остаются неиспользованными, например, класс B может никогда не вызывать onTaskFailed()
. Нормально ли, что некоторые методы полностью не используются?
Комментарии:
1. интерфейс — лучший способ уведомить пользователя. другой способ заключается в том, что вы можете использовать android.jlelse.eu /… и developer.android.com/reference/android/support/v4/content /…
Ответ №1:
Android имеет очень хорошую стороннюю библиотеку, такую как EventBus https://github.com/greenrobot/EventBus
Вы можете ознакомиться с его документацией, очень простой в использовании.
public class A{
onCreate(){
B objectB = new B();
objectB.loginUser(username,password); //no need to pass callback
@Subscribe(threadMode = ThreadMode.MAIN)
public void onSuccessEvent(SuccessEvent successEvent) {
//this is called when task is successful
}
@Subscribe(threadMode = ThreadMode.MAIN)
public void onErrorEvent(ErrorEventsuccessEvent) {
//this is called when task is failed
}
}
public class B{
public void loginUser(String username, String password){
//after task is performed
if(task.isSuccessful()){
EventBus.getDefault().post(new SuccessEvent("Successful"));
}else{
EventBus.getDefault().post(new ErrorEvent("Programming is fun they said..."));
}
}
Ваши классы событий
public class SuccessEvent {
private String message;
public SuccessEvent(String message) {
this.message=message;
}
}
public class ErrorEvent {
private String message;
public ErrorEvent(String message) {
this.message=message;
}
}
Комментарии:
1. в чем преимущество перед обычными классами интерфейса?
2. При разработке программного обеспечения мы всегда следуем некоторой архитектуре, например, в Advance java для веб-разработки я следовал MVC. То же самое в разработке Android, мы следуем MVP, MVVM и т.д. В MVP мы пишем каждый класс отдельно и независимо. Также принцип SOLID гласит, что класс должен иметь только одну функциональность. Теперь, используя шину событий поверх интерфейса, нам не нужно передавать реализованный класс интерфейса поверх класса бизнес-логики. Таким образом, наш код класса бизнес-логики независим, и это упрощает тестирование и обслуживание кода. Я думаю, вам следует сначала проверить MVP и принцип программирования SOLID.
3. @AlphaTester, вы можете видеть, что ваш класс B зависит от интерфейса MyCallback. это тесно связанный код. но использование класса EventBus B даже не знает, кому он отправляет результат в качестве обратного вызова. Вы можете полностью исключить интерфейс.
Ответ №2:
Я нашел ответ на вопрос внизу: т. Е. Методы интерфейса не используются.
Чтобы решить эту проблему, я использовал абстрактный класс! т. Е. абстрактный класс будет реализовывать все обратные вызовы интерфейса. Затем при передаче обратного вызова просто передайте экземпляр абстрактного класса вместо интерфейса. Таким образом, для получения результата может быть переопределен только метод *required.