Я создаю приложение Android и столкнулся с кирпичной стеной, когда звонил в JCDecaux Publi c Bike API.
Это пример данных, которые я ожидаю получить от API (несколько таких записей, по одной на Bike Station):
{"number":42,"contract_name":"contract","name":"name","address":"some road","position":{"lat":1.234567,"lng":-1.234567},"banking":true,"bonus":false,"bike_stands":30,"available_bike_stands":18,"available_bikes":12,"status":"OPEN","last_update":1586356088000},
, где number
- уникальный идентификатор и позиция дает мне географические координаты точки на земном шаре. Единственная информация, которая меня интересует, это address
(используется в другом классе, не показанном здесь), available_bikes
, available_bike_stands
, а также параметр number
, который я буду использовать в качестве идентификатора для выяснить, с каким элементом взаимодействует пользователь.
Я пытался использовать Ion (зависимость com.koushikdutta.ion:ion:3.0.8
), так как в будущем выпуске приложения будут изображения, связанные с каждой записью в JSON, но это приводит к аварийному завершению моего приложения с java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String c.a.c.b.h()' on a null object reference
где-то. Ниже приведено то, что я написал до сих пор:
public class APICaller {
private Context context;
public APICaller(Context context) {
this.context = context;
}
// These two are used to make callbacks so that that the methods calling this class and its
// fetchers are then able to work on the results without constantly polling to see if the result changed.
public interface OnReturnBikeStationList {
void onSuccess(ArrayList<BikeStation> value);
}
// Same as above.
public interface OnFetchBikeStationDetails {
void onSuccess(Boolean result);
}
// Gets a single Bike Station as input -> Fetches all relevant information
// regarding the Bike Station and stores it inside the object
public void getBikeStationInformation(BikeStation bikeStation, OnFetchBikeStationDetails callback) {
int id = bikeStation.getBikeStationId();
new Thread(new Runnable() {
@Override
public void run() {
OkHttpClient client = new OkHttpClient();
Request request = new Builder()
.url(API_URL)
.get()
.build();
try {
Response response = client.newCall(request).execute();
JsonElement responseJson = new JsonParser().parse(response.body().string());
// If this check didn't pass, there's an issue - it should.
if (responseJson.isJsonObject()) {
JsonObject element = responseJson.getAsJsonObject();
callback.onSuccess(true);
}else{
Log.d("Error", "Had issues parsing bike station information for bikeStation: " + bikeStation.getBikeStationId());
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}).start();
}
public void fetchBikeStations(OnReturnBikeStationList callback) {
ArrayList<BikeStation> bikeStations = new ArrayList<>();
new Thread(new Runnable() {
@Override
public void run() {
OkHttpClient client = new OkHttpClient();
Request request = new Builder()
.url(
" https://api.jcdecaux.com/vls/v1/stations?contract=dublin&apiKey=" + API_KEY)
.get()
.build();
try {
Response response = client.newCall(request).execute();
JsonElement responseJson = new JsonParser().parse(response.body().string());
if (responseJson.isJsonArray()) {
responseJson.getAsJsonArray().forEach((element) -> {
bikeStations.add(buildBikeStation(element.getAsJsonObject()));
});
callback.onSuccess(bikeStations);
}
} catch (Exception ex) {
ex.printStackTrace();
Toaster.toast(context.getString(R.string.error_api_message));
}
}
}).start();
}
private BikeStation buildBikeStation(JsonObject element) {
JsonObject returnObject = element.getAsJsonObject();
Integer bikesAvailable = Integer.parseInt(returnObject.get("available_bikes").toString());
String name = returnObject.get("name").getAsString();
Integer id = Integer.parseInt(returnObject.get("number").toString());
Integer parkingAvailable = Integer.parseInt(returnObject.get("available_bike_stands").toString());
BikeStation bikeStation = new BikeStation(name, id, bikesAvailable, parkingAvailable);
return bikeStation;
}
}
Вот как я вставляю в переработчик. Вид
new APICaller(this).fetchBikeStations(formattedInput, 25, 1, new OnReturnBikeStationList() {
@Override
public void onSuccess(ArrayList<BikeStation> value) {
// Clear past results.
bikeStationHeaders.clear();
// Insert into the recyclerview.
for (BikeStation bikeStation : value) {
bikeStationHeaders.add(bikeStation.getName());
{~SIMILAR APPROACH FOR ALL OTHER FIELDS~}
}
Пожалуйста, не стесняйтесь спрашивать разъяснения где угодно, я сделаю все возможное, чтобы предоставить необходимую информацию, где это возможно. Большое спасибо.