Запрос данных из API и добавление в RecyclerView - PullRequest
0 голосов
/ 08 апреля 2020

Я создаю приложение 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~}

          }

Пожалуйста, не стесняйтесь спрашивать разъяснения где угодно, я сделаю все возможное, чтобы предоставить необходимую информацию, где это возможно. Большое спасибо.

...