Android翻新解析列表中的嵌套json响应 [英] Android retrofit parse nested json response in List
问题描述
我正在创建一个基于News API的Android应用程序,该程序使用RecyclerView将特定频道(例如ABC新闻)的新闻加载到MainFragment中.
I am creating a News API based Android application which loads the news of a particular channel say ABC News into MainFragment using a RecyclerView.
我正在MainFragment中为此进行API调用:
I am making an API Call for that in MainFragment as follows:
MainFragment.java
MainFragment.java
public class MainFragment extends Fragment
{
protected RecyclerView recyclerView;
protected NewsAdapter adapter;
protected String API_KEY;
String sourceTitle, sourceID;
List<Articles> articleList;
public MainFragment() {
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState)
{
ViewGroup root = (ViewGroup) inflater.inflate(R.layout.fragment_main, null);
sourceTitle = "ABC News";
sourceID = "abc-news";
getActivity().setTitle(sourceTitle);
API_KEY = getString(R.string.API_KEY);
recyclerView = root.findViewById(R.id.recyclerview);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getActivity().getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);
Call<News> call = apiService.getArticles(sourceID, API_KEY);
call.enqueue(new Callback<News>()
{
@Override
public void onResponse(Call<News> call, Response<News> response)
{
if (response != null && response.isSuccessful())
{
articleList = response.body().getArticles();
populateRecycleView();
}
else
{
Toast.makeText(getActivity(), "Something went wrong..", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onFailure(Call<News> call, Throwable t)
{
Toast.makeText(getActivity(), "Error in API Call", Toast.LENGTH_SHORT).show();
}
});
recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getActivity().getApplicationContext(), recyclerView, new ClickListener() {
@Override
public void onClick(View view, int position)
{
//onclick code
}
@Override
public void onLongClick(View view, int position) {
}
}));
return root;
}
private void populateRecycleView()
{
if (articleList.isEmpty() || articleList.size() == 0)
{
recyclerView.setAdapter(null);
Toast.makeText(getActivity(), "Error in List", Toast.LENGTH_SHORT).show();
}
else
{
adapter = new NewsAdapter(articleList, getActivity());
recyclerView.setAdapter(adapter);
}
}
执行articleList = response.body().getArticles()
时
发生错误,并且arraylist仍然为空.
While executing the articleList = response.body().getArticles()
an error occurs, and the arraylist is still empty.
API调用不会在其中加载值.
The API call doesn't load values inside it.
我已经创建了两个Retrofit类:APIInterface和APIClient,它们执行GET API调用:https://newsapi.org/v2/top-headlines?sources=abc-news&apiKey=MY_API_KEY
.
I have created two Retrofit classes: APIInterface and APIClient that executes the GET API call: https://newsapi.org/v2/top-headlines?sources=abc-news&apiKey=MY_API_KEY
.
APIInterface.java
APIInterface.java
public interface ApiInterface
{
@GET("top-headlines")
Call<List<News>> getArticles(@Query("sources") String source, @Query("apiKey") String apiKey);
}
APIClient.java
APIClient.java
public class ApiClient
{
public static final String BASE_URL = "https://newsapi.org/v2/";
private static Retrofit retrofit = null;
public static Retrofit getClient()
{
if (retrofit==null)
{
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
我无法理解我是否在上述两个类中进行了正确的API调用,因为在我的arctilesList列表和数组适配器中没有解析JSON数据.
I am unable to understand whether I am making the right API call in the above two classes, because the JSON data is not getting parsed in my arctilesList List and in my array adapter.
应用程序在执行API调用时崩溃.
The Application crashes in the API call execution.
请注意:API调用有效.适配器已成功加载API结果.
Please note: API calls working. The adapter is getting successfully loaded with the API results.
推荐答案
First thing you need to understand is, Retrofit's Call#enqueue()
method is Asynchronous. Your code executes top to bottom. Mean time enqueue()
method initiates an asynchronous request to API and returns success response to onResponse()
method if it is successful else onFailure()
method.
那么,如何解决代码问题?
So, how to fix your code problem?
首先,您需要为API响应创建POJO类(如果尚未创建),如下所示.
First thing you need to create POJO classes (if you haven't created yet) for API response like below.
Article.java
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Article {
@SerializedName("source")
@Expose
private Source source;
@SerializedName("author")
@Expose
private String author;
@SerializedName("title")
@Expose
private String title;
@SerializedName("description")
@Expose
private String description;
@SerializedName("url")
@Expose
private String url;
@SerializedName("urlToImage")
@Expose
private Object urlToImage;
@SerializedName("publishedAt")
@Expose
private String publishedAt;
@SerializedName("content")
@Expose
private String content;
// constructors
// getters and setter methods
// use Alt + Insert to generate constructors, getter and setter methods in Android Studio
}
Source.java
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Source {
@SerializedName("id")
@Expose
private String id;
@SerializedName("name")
@Expose
private String name;
// constructors
// getters and setter methods
}
News.java
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class News {
@SerializedName("status")
@Expose
private String status;
@SerializedName("totalResults")
@Expose
private Integer totalResults;
@SerializedName("articles")
@Expose
private List<Article> articles = null;
// constructors
// getters and setter methods
}
现在在您的 MainFragment 类中进行以下更改,
Now in your MainFragment class do the below changes,
public class MainFragment extends Fragment {
// other part of the code here
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
// other part of the code here
call.enqueue(new Callback<News>() {
@Override
public void onResponse(Call<News> call, Response<News> response) {
if (response != null && response.isSuccessful()) {
articleList = response.body().getArticles();
// request is successful just populate data in RecyclerView
populateRecyclerView();
} else {
Toast.makeText(getActivity(), "Something went wrong...", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onFailure(Call<News> call, Throwable t) {
Toast.makeText(getActivity(), "Error in API Call", Toast.LENGTH_SHORT).show();
}
});
// just move ArrayList checking and setting adapter part code into some other method
// other part of the code here
}
private void populateRecyclerView() {
if (articleList.isEmpty() || articleList.size() == 0) {
recyclerView.setAdapter(null);
Toast.makeText(getActivity(), "Error in List", Toast.LENGTH_SHORT).show();
} else {
adapter = new NewsAdapter(articleList, getActivity());
recyclerView.setAdapter(adapter);
}
}
}
不要忽略onFailure()
方法中的Throwable对象.只需记录错误消息,而不是在Toast中显示错误消息即可.
Do not ignore Throwable object in onFailure()
method . Just log the error messages instead of showing error messages in Toast.
Log.e("TAG", "Error occurred...", t);
通过这种方式,您可以轻松地找出执行API请求时出了什么问题.
This way you could easily find out what went wrong while executing API request.
我跳过了答案中的部分代码,因为它是正确的,并且使答案有点长.请仔细查看我在答案中使用的方法名称和注释.
I skipped some part of your code in my answer as it's correct and makes my answer little long. Please look into method name and comments I've used in my answer properly.
这篇关于Android翻新解析列表中的嵌套json响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!