#java #android #json #retrofit #retrofit2
#java #Android #json #модернизация #retrofit2
Вопрос:
Я пытаюсь получить данные JSON https://newsapi.org/v1/articles
с помощью Retrofit, но я новичок в этом, и до сих пор это было довольно запутанно.
Из того, что я могу сказать, мне удалось установить успешное соединение. Однако по какой-то причине, которую я еще не смог определить, Retrofit не сопоставляет данные из строк JSON с моим NewsAPI
классом.
Я опубликую код, который я использую в настоящее время, и я надеюсь, что кто-нибудь поможет мне разобраться в этом. Спасибо!
Activity.java
:
final TextView tvTest = (TextView) findViewById(R.id.tvTest);
String url = "https://newsapi.org";
NewsAPI_Interface client = NewsAPI_Adapter.createService(NewsAPI_Interface.class);
Call<List<NewsAPI>> call = client.getData("techcrunch", "APIkeygoeshere");
call.enqueue(new Callback<List<NewsAPI>>() {
@Override
public void onResponse(Call<List<NewsAPI>> call, Response<List<NewsAPI>> response) {
if (response.body() != null) {
tvTest.setText(response.body().toString());
for (NewsAPI news: response.body()) {
System.out.println(news.source " (" news.status ")");
tvTest.setText(news.source " (" news.status ")");
}
} else {
tvTest.setText("It's null, " response.errorBody().toString() ", " call.request().url());
}
}
@Override
public void onFailure(Call<List<NewsAPI>> call, Throwable t) {
tvTest.setText("An error ocurred!");
}
});
NewsAPI.java
:
public class NewsAPI {
String status;
String source;
public NewsAPI (String status, String source) {
this.status = status;
this.source = source;
}
}
NewsAPI_Interface.java
:
public interface NewsAPI_Interface {
@GET("/v1/articles")
Call<List<NewsAPI>> getData(@Query("source") String source, @Query("api_Key") String api_key);
}
NewsAPI_Adapter.java
:
public class NewsAPI_Adapter {
public static final String API_BASE_URL = "https://newsapi.org";
private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
private static Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create());
public static <S> S createService(Class<S> serviceClass) {
Retrofit retrofit = builder.client(httpClient.build()).build();
return retrofit.create(serviceClass);
}
}
Комментарии:
1. Если я помню, вы можете использовать только
response.body()
один раз изonResponse
метода2. Используете ли вы proguard?
3. Кроме того,
@Query("api_Key")
должно бытьapiKey
, если я правильно читаю. newsapi.org4. И обратный вызов определен неправильно. Вы не ожидаете список, вы ожидаете один
NewsAPI
объект.
Ответ №1:
Из того, что я могу сказать, мне удалось установить успешное соединение
Ну, вы игнорируете Throwable здесь, где будет выведена ошибка.
@Override
public void onFailure(Call<List<NewsAPI>> call, Throwable t) {
tvTest.setText("An error ocurred!");
}
Ожидаемый вами ответ выглядит следующим образом
{
"status": "ok",
"source": "techcrunch",
...
{
Там начинается объект, а не a List
, поэтому вы должны определить свой интерфейс по-другому. Затем в документации говорится, что ключ API добавляется к URL с apiKey
помощью, поэтому измените это.
public interface NewsAPI_Interface {
@GET("/v1/articles")
Call<NewsAPI> getData(@Query("source") String source, @Query("apiKey") String api_key);
}
(Вам нужно определить другой объект для Article
класса. Но это проблема Gson, а не модернизация)
Наконец, я помню, что где-то читал, что response.body()
его следует вызывать только один раз.
Call<NewsAPI> call = client.getData("techcrunch", "APIkeygoeshere");
call.enqueue(new Callback<NewsAPI>() {
@Override
public void onResponse(Call<List<NewsAPI>> call, Response<List<NewsAPI>> response) {
final NewsAPI responseBody = response.body();
if (responseBody != null) {
tvTest.setText(responseBody.toString());
String news = news.source " (" news.status ")";
Log.i("responseBody", news);
tvTest.setText(news);
} else {
tvTest.setText("It's null, " response.errorBody().toString() ", " call.request().url());
}
}
@Override
public void onFailure(Call<List<NewsAPI>> call, Throwable t) {
tvTest.setText("An error ocurred!");
Log.e("news Error", t.getMessage());
}
});
Удачи!
Комментарии:
1. Спасибо, теперь у меня все работает! Я также успешно реализовал отсутствующий
Articles
класс, который был необходим для сопоставления массива JSON, используяArrayList<Articles>
on в соответствующей переменнойNewsAPI
класса. Просто оставляю это здесь для дальнейшего использования.2. Привет, Kalz, я следил за этим моментом, как вы получили ArrayList<Articles> из ответа, я использую тот же api