Android翻新解析列表中的嵌套json响应 [英] Android retrofit parse nested json response in List

查看:80
本文介绍了Android翻新解析列表中的嵌套json响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建一个基于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.

推荐答案

您需要了解的第一件事是Retrofit的

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆