Я переписываю некоторые части приложения Android для вызова REST-сервера, написанного на Java, используя Spring-Boot Framework.
Подводя итог, скажем, в приложении, функции Aвызывает функцию B в моем главном контроллере (который должен управлять связью клиент-сервер).Вызов функции B (с несколькими дополнительными шагами) вызывает мой Сервер.Когда функция B выполняет вызов, она использует анонимный внутренний класс, переопределяющий метод, чтобы определить, как обрабатывать ответ.Я изо всех сил пытаюсь получить этот ответ от анонимного внутреннего класса к функции B, чтобы его можно было вернуть к функции A. К сожалению, некоторая асинхронность задействована, просто чтобы сделать вещи, которые немного более интересными.использовать карту, которая хранит результат вызова с уникальным идентификатором, чтобы сделать его доступным за пределами внутреннего класса.Теоретически работает довольно хорошо, но рассыпается под асинхронностью
Во-вторых, я тупо добавил цикл, который должен ждать, пока результат будет помещен в карту, прежде чем продолжить, убедившись, что есть что вернуть.
Каким-то образом цикл не выполняется должным образом (я полагаю), и когда я использую цикл, вызов на мой сервер никогда не завершается (что происходит при отсутствии цикла)
См. Следующеекод
Клиент: MainController
class MainController
{
private final AtomicLong counter;
private final HashMap<Long, Object> callResults;
public MainController(){
counter = new AtomicLong();
callResults = new HashMap<>();
}
public Login getLoginByUsername(String username)
{
long callID = counter.incrementAndGet();
System.out.println("Start call");
ServerConnection.get("myURL",null, new JsonHttpResponseHandler(){
@Override
public void onSuccess(int statusCode, Header[] headers, JSONObject response){
try {
System.out.println("Call success, enter result:");
callResults.put(callID, new CallResult(Login.parseFromJson(response)));
System.out.println(callResults.get(callID));
} catch (JSONException e) {
e.printStackTrace();
}
}
});
System.out.println("start waiting");
while(callResults.get(callID) == null){
System.out.print(".");
}
System.out.println("waiting over, return result:");
System.out.println(callResults.get(callID));
//return (Login) callResults.remove(callID).content;
return null;
}
}
Клиент: ServerConnection
import com.loopj.android.http.*;
import cz.msebera.android.httpclient.HttpEntity;
public class ServerConnection {
private static final String BASE_URL = "http://1.3.3.7:8080/";
private static AsyncHttpClient client = new AsyncHttpClient();
public static void get(String url, RequestParams params, JsonHttpResponseHandler responseHandler) {
client.get(BASE_URL+url, params, responseHandler);
}
}
Вот что я знаю:
Намеченный ответ придет в конце концов.Когда я не использую цикл ожидания и просто возвращаю ноль, на консоли будут отображаться сообщения «Успешный вызов, введите результат:» и идентификатор объекта
При использовании whileк концу, он никогда не печатает "."- это просто ничего не делает.Я знаю, что приложение все еще работает, потому что AndroidStudio продолжает информировать меня о распределении пространства
Попытка применить шаблон наблюдателя может оказаться вне области видимости.Мне бы пришлось по-настоящему углубиться в клиентский код, который я бы предпочел не трогать.Приведенный мною код не совсем прост для работы, если честно
Это, как я полагаю, проблема: цикл предотвращает выполнение асинхронного REST-вызова,таким образом делая невозможным завершение.
Мой вопрос: A) Как я могу вернуть объект Login, полученный мной от сервера, в функцию, которая сначала вызывала функцию MainController.getLoginByUsername-function?
B) Что происходит с циклом while, который я пытался использовать для ожидания?Почему тело (print(".");
) не будет выполнено и, что более важно, почему оно останавливает выполнение / завершение формы вызова REST?
(также не стесняйтесь оставлять отзыв о моем стиле публикации,я впервые задаю вопрос здесь)
Редактировать: добавлен вопрос B, который может предоставить более простой способ найти быстрое решение
Изменить на ОБНОВЛЕНИЕ: Извините, что не прояснил это достаточно:любое предложение, которое также требует от меня адаптации вызывающей функции (например, шаблоны наблюдателя, такие как Livedata
или Rxjava
или другие действительно хорошие предложения, предоставленные Лео Пелозо), неосуществимо.Я проверил, по крайней мере, предложение Лео Пелозоса, и основной код просто не позволяет этого.Я теряю доступ к параметрам и больше не могу использовать функцию возврата.Я знаю, что переделка базовой системы была бы лучшим вариантом действий, но сейчас это просто выходит за рамки ...