【问题标题】:how to retrieve data from api on java android and use it?如何从java android上的api检索数据并使用它?
【发布时间】:2020-11-20 04:00:57
【问题描述】:

大家好,感谢您帮助我,

我正在尝试从 api 网址“https://api.stackexchange.com/2.2/search?order=desc&sort=creation&site=stackoverflow&tagged=android”获取数据,但我不知道我错过了什么。 我不断收到一条错误消息,提示我指向一个空对象,但它不应该为空。

这是错误信息


`
        E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.finalhomework, PID: 5005
    java.lang.NullPointerException: Attempt to invoke interface method 'java.util.Iterator java.util.List.iterator()' on a null object reference
        at com.example.finalhomework.view.SearchActivity$1.onResponse(SearchActivity.java:46)
        at retrofit2.DefaultCallAdapterFactory$ExecutorCallbackCall$1.lambda$onResponse$0$DefaultCallAdapterFactory$ExecutorCallbackCall$1(DefaultCallAdapterFactory.java:89)
        at retrofit2.-$$Lambda$DefaultCallAdapterFactory$ExecutorCallbackCall$1$3wC8FyV4pyjrzrYL5U0mlYiviZw.run(lambda)
        at android.os.Handler.handleCallback(Handler.java:751)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6077)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:866)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:756)`

那是应该得到所有项目的结果页面

`
        package com.example.finalhomework.model;

import java.io.Serializable;
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class StackOverflowPageResult implements Serializable
{

    @SerializedName("StackOverflowItem")
    @Expose
    private List<StackOverflowItem> items = null;
    @SerializedName("has_more")
    @Expose
    private Boolean hasMore;
    @SerializedName("quota_max")
    @Expose
    private Integer quotaMax;
    @SerializedName("quota_remaining")
    @Expose
    private Integer quotaRemaining;
    private final static long serialVersionUID = -263378404000205617L;

    public List<StackOverflowItem> getStackOverflowItem() {
        return items;
    }

    public void setItems(List<StackOverflowItem> items) {
        this.items = items;
    }

    public Boolean getHasMore() {
        return hasMore;
    }

    public void setHasMore(Boolean hasMore) {
        this.hasMore = hasMore;
    }

    public Integer getQuotaMax() {
        return quotaMax;
    }

    public void setQuotaMax(Integer quotaMax) {
        this.quotaMax = quotaMax;
    }

    public Integer getQuotaRemaining() {
        return quotaRemaining;
    }

    public void setQuotaRemaining(Integer quotaRemaining) {
        this.quotaRemaining = quotaRemaining;
    }

}`

这就是物品本身:

`
        package com.example.finalhomework.model;

import java.io.Serializable;
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;

public class StackOverflowItem implements Serializable
{

    @SerializedName("tags")
    @Expose
    private List<String> tags = null;
    @SerializedName("owner")
    @Expose
    private Owner owner;
    @SerializedName("is_answered")
    @Expose
    private Boolean isAnswered;
    @SerializedName("view_count")
    @Expose
    private Integer viewCount;
    @SerializedName("answer_count")
    @Expose
    private Integer answerCount;
    @SerializedName("score")
    @Expose
    private Integer score;
    @SerializedName("last_activity_date")
    @Expose
    private Integer lastActivityDate;
    @SerializedName("creation_date")
    @Expose
    private Integer creationDate;
    @SerializedName("question_id")
    @Expose
    private Integer questionId;
    @SerializedName("content_license")
    @Expose
    private String contentLicense;
    @SerializedName("link")
    @Expose
    private String link;
    @SerializedName("title")
    @Expose
    private String title;
    @SerializedName("last_edit_date")
    @Expose
    private Integer lastEditDate;
    @SerializedName("accepted_answer_id")
    @Expose
    private Integer acceptedAnswerId;
    @SerializedName("closed_date")
    @Expose
    private Integer closedDate;
    @SerializedName("closed_reason")
    @Expose
    private String closedReason;
    private final static long serialVersionUID = 2088551364601451752L;

    public List<String> getTags() {
        return tags;
    }

    public void setTags(List<String> tags) {
        this.tags = tags;
    }

    public Owner getOwner() {
        return owner;
    }

    public void setOwner(Owner owner) {
        this.owner = owner;
    }

    public Boolean getIsAnswered() {
        return isAnswered;
    }

    public void setIsAnswered(Boolean isAnswered) {
        this.isAnswered = isAnswered;
    }

    public Integer getViewCount() {
        return viewCount;
    }

    public void setViewCount(Integer viewCount) {
        this.viewCount = viewCount;
    }

    public Integer getAnswerCount() {
        return answerCount;
    }

    public void setAnswerCount(Integer answerCount) {
        this.answerCount = answerCount;
    }

    public Integer getScore() {
        return score;
    }

    public void setScore(Integer score) {
        this.score = score;
    }

    public Integer getLastActivityDate() {
        return lastActivityDate;
    }

    public void setLastActivityDate(Integer lastActivityDate) {
        this.lastActivityDate = lastActivityDate;
    }

    public Integer getCreationDate() {
        return creationDate;
    }

    public void setCreationDate(Integer creationDate) {
        this.creationDate = creationDate;
    }

    public Integer getQuestionId() {
        return questionId;
    }

    public void setQuestionId(Integer questionId) {
        this.questionId = questionId;
    }

    public String getContentLicense() {
        return contentLicense;
    }

    public void setContentLicense(String contentLicense) {
        this.contentLicense = contentLicense;
    }

    public String getLink() {
        return link;
    }

    public void setLink(String link) {
        this.link = link;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public Integer getLastEditDate() {
        return lastEditDate;
    }

    public void setLastEditDate(Integer lastEditDate) {
        this.lastEditDate = lastEditDate;
    }

    public Integer getAcceptedAnswerId() {
        return acceptedAnswerId;
    }

    public void setAcceptedAnswerId(Integer acceptedAnswerId) {
        this.acceptedAnswerId = acceptedAnswerId;
    }

    public Integer getClosedDate() {
        return closedDate;
    }

    public void setClosedDate(Integer closedDate) {
        this.closedDate = closedDate;
    }

    public String getClosedReason() {
        return closedReason;
    }

    public void setClosedReason(String closedReason) {
        this.closedReason = closedReason;
    }

}`

那是带有 url 的 Retrofit 构建器:

`
        package com.example.finalhomework.network;

import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class RetrofitInstance {

    private static Retrofit retrofit;
    private static final String BASE_URL ="https://api.stackexchange.com/2.2/";

    public static Retrofit getRetrofitInstance(){

        if (retrofit == null){

            retrofit = new retrofit2.Retrofit.Builder()
                    .baseUrl(BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build();
        }

        return retrofit;
    }
}`

那是带有url参数的接口:

`
        package com.example.finalhomework.network;

import com.example.finalhomework.model.StackOverflowPageResult;

import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Query;

public interface GetStackOverflowItemDataService {

    @GET("search")
    Call<StackOverflowPageResult> getStackOverflowItem(
            @Query("tagged") String tagged,
            @Query("site") String site,
            @Query("sort") String sort,
            @Query("order") String order

    );
}`

在这里,我们得到了应该得到总结果的类,我放了一个 Log.i 来检查一切是否正常,并且 stackOverflowItems 为空:

`
        package com.example.finalhomework.view;

import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;

import android.os.Bundle;
import android.util.Log;

import com.example.finalhomework.R;
import com.example.finalhomework.model.StackOverflowItem;
import com.example.finalhomework.model.StackOverflowPageResult;
import com.example.finalhomework.network.GetStackOverflowItemDataService;
import com.example.finalhomework.network.RetrofitInstance;

import java.util.List;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class SearchActivity extends AppCompatActivity {

    Toolbar toolbar;
    private GetStackOverflowItemDataService stackOverflowItemDataService;
    List<StackOverflowItem> stackOverflowItems;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_search);

        setToolbarBack();

        stackOverflowItemDataService = RetrofitInstance.getRetrofitInstance().create(GetStackOverflowItemDataService.class);
        stackOverflowItemDataService.getStackOverflowItem("android", "stackoverflow", "creation", "desc")
                .enqueue(new Callback<StackOverflowPageResult>() {
                    @Override
                    public void onResponse(Call<StackOverflowPageResult> call, Response<StackOverflowPageResult> response) {

                        StackOverflowPageResult stackOverflowPageResult = response.body();

                        stackOverflowItems = stackOverflowPageResult.getStackOverflowItem();


                        for (StackOverflowItem s : stackOverflowItems) {
                            Log.i("Item StackOverflow :", s.getTitle());
                        }

                    }

                    @Override
                    public void onFailure(Call<StackOverflowPageResult> call, Throwable t) {

                    }
                });
    }`

再次感谢您的帮助

【问题讨论】:

    标签: java android api gson retrofit2


    【解决方案1】:

    JSON 数据变量与您的 @SerializedName("StackOverflowItem") 不匹配

    所以进行更改以匹配 SerializedName,代码如下 -

    public class StackOverflowPageResult implements Serializable {
            
        @SerializedName("items")
        private List<StackOverflowItem> items;
    
        @SerializedName("has_more")
        private Boolean hasMore;
    
        @SerializedName("quota_max")
        private Integer quotaMax;
    
        @SerializedName("quota_remaining")
        private Integer quotaRemaining;
        
        // your further code here
        //.............
    }
    

    SerializedName 仅当您要使用不同于 JSON 对象的变量名时才需要,否则您也可以跳过 @SerializedName 标签。

    还有一件事我建议,如果你不打算在你的 GsonBuilder 类中调用excludeFieldsWithoutExposeAnnotation(),那么就不需要@Expose 标签了。

    Gson @Expose 注解可用于标记要公开或不公开(包含或不包含)的字段以进行序列化或反序列化。 @Expose 注释可以接受两个参数,每个参数都是一个布尔值,可以取值 true 或 false。为了让 GSON 对 @Expose 注释做出反应,我们必须使用 GsonBuilder 类创建一个 Gson 实例,并且需要调用 excludeFieldsWithoutExposeAnnotation() 方法,它将 Gson 配置为排除所有不考虑序列化或反序列化的字段公开注释。

    编码愉快!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-01-11
      • 2020-02-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-02
      • 2019-03-20
      相关资源
      最近更新 更多