#java #android #asynchronous #android-volley
#java #Android #асинхронный #android-volley
Вопрос:
Я пишу приложение в Android Studio, которое уведомляет пользователя о времени поезда. У меня есть класс под названием Journey, и моя идея (не уверен, что это правильный способ сделать это, поскольку я новичок в разработке на Java и Android) состоит в том, чтобы установить атрибуты на основе возвращаемого ответа от API. Вызов API работает, и я могу установить атрибуты, но как я могу сделать так, чтобы вызывающий класс прослушивал до тех пор, пока он не завершит вызов API и полностью не загрузит атрибуты.
Код, который у меня есть на данный момент, выглядит следующим образом:
public Journey(String startCode, String endCode, Activity activity) {
//Connect to the API and set up the journey object
updateJourney(startCode,endCode,activity);
}
public void updateJourney(String startCode, final String endCode, Activity activity) {
queue = Volley.newRequestQueue(activity);
final Journey journeyClass = this;
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(Request.Method.GET,URL_LEFT URL_START startCode URL_DEST endCode,null,
new Response.Listener<JSONArray>() {
@Override
public void onResponse(JSONArray response) {
Log.d("Response", response.toString());
if (response.length() != 0) {
try {
JSONObject returnedJourney = response.getJSONObject(0);
journeyClass.setStartCode(returnedJourney.getString("station"));
journeyClass.setEndCode(endCode);
JSONArray services = returnedJourney.getJSONArray("services");
JSONObject firstService = services.getJSONObject(0);
journeyClass.setDepartTime(firstService.getString("depfriendly"));
journeyClass.setArriveTime(firstService.getString("arrfriendly"));
journeyClass.setStatus(firstService.getString("schedule_status"));
Log.d("journey arrival",journeyClass.getArriveTime());
} catch (JSONException e) {
e.printStackTrace();
}
} else {
//Returned response is empty - deal wth
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
// TODO: Handle error
//Log.d("URL", URL_LEFT URL_START startCode URL_DEST endCode);
VolleyLog.d("error", error.getMessage());
error.printStackTrace();
}
});
queue.add(jsonArrayRequest);
}
Вероятно, существует определенный способ выполнения всего этого, но, как я уже сказал, я очень новичок в этом. Я искал в Интернете, но не совсем уверен, как именно вы это делаете на Java. Я не уверен, правильно ли настроен экземпляр класса, но это то, о чем я думал как о способе установки атрибутов внутри внутреннего класса.
Обновить:
Я использую приведенное ниже в прослушивателе, которое, похоже, может работать. Мне нужно будет привести в порядок весь код, и я вернусь позже, если это сработает как решение. Мне нужно идти на работу в течение следующих 8 часов.
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
TextView station = getActivity().findViewById(stationFieldId);
station.setText(stationName);
TextView timeField = getActivity().findViewById(timeFieldId);
timeField.setText(journey.getDepartTime());
}
});
Комментарии:
1. Я не уверен, правильно ли я понял, вы хотите, чтобы вызывающий класс получал уведомление, как только ответ будет либо успешным, либо неудачным? пожалуйста, уточните
2. Насколько я понимаю, вызов API происходит асинхронно, поэтому в классе fragment, который вызывает конструктор, происходит сбой, если вы запускаете Log.d(«journey arrival»,journey.getArriveTime()); после вызова конструктора. Мое предположение о том, что там происходит, заключается в том, что он еще не завершил вызов API, поскольку объект создается классом response listener.
3. Я попытался переместить вызов API в вызывающий класс, но столкнулся с той же проблемой. Если я пытаюсь обновить TextView изнутри прослушивателя, я получаю исключение null object. Я не могу найти в Интернете ничего, что объясняет, как это четко сделать. Кто-нибудь может помочь?
4. Вы пишете сетевую логику для запроса чего-либо в другом классе и используете listener для передачи данных обратно в target, Нарисуйте диаграмму, что вам нужно.
5. Я не уверен, как нарисовать его диаграмму, но в основном мне нужно выполнить вызов API, а затем обновить TextView в пользовательском интерфейсе данными, полученными из API.
Ответ №1:
Это код, который я использовал в конце, который сработал для меня. Я отредактировал многое из того, что он делает с элементами пользовательского интерфейса, чтобы включить ту часть, где он устанавливает текстовые представления
private void getJourneyAndDisplay(String startCode, final String destCode, final String stationName, final int stationFieldId, final int timeFieldId, final int statusFieldId, final boolean out) {
queue = Volley.newRequestQueue(getActivity());
journey = new Journey();
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(Request.Method.GET, Journey.URL_LEFT Journey.URL_START startCode Journey.URL_DEST destCode, null,
new Response.Listener<JSONArray>() {
@Override
public void onResponse(JSONArray response) {
if (response.length() != 0) {
try {
//Make panel visible as it has returned results
panel.setVisibility(View.VISIBLE);
JSONArray services = returnedJourney.getJSONArray("services");
if (services.length() > 0) {
//Journey object is configured
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
Activity act = getActivity();
TextView station = act.findViewById(stationFieldId);
station.setText(stationName);
TextView timeField = act.findViewById(timeFieldId);
timeField.setText(journey.getDepartTime());
TextView statusField = act.findViewById(statusFieldId);
statusField.setText(journey.getStatus());
}
});
} else {
//Deal iwth no joruney
}
} catch (JSONException e) {
//Display message to inform user that the data cannot be retrieved
}
} else {
//Returned response is empty
}
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
//Handle reponse
}
});
queue.add(jsonArrayRequest);
}