【问题标题】:Retrofit onResponse method not working, throws NullPointerException [duplicate]改造 onResponse 方法不起作用,抛出 NullPointerException [重复]
【发布时间】:2016-08-18 20:32:47
【问题描述】:

我正在尝试从 Web API 获取数据,但我的 onResponse() 方法有问题,我无法弄清楚。

我的 JSON 看起来像这样

  [
   "partner1",
   "partner2",
   "partner3",
     ...     ,
   "partner150"
  ]

我有 Table 合作伙伴 (ActiveAndroid),我想从 API 中保存所有合作伙伴。

@Table(name = "Partners")
public class Partners extends Model {

    @Column(name = "Name")
    String name;

    public Partners() {}

    public Partners(String name) {
        this.name = name;
    }
}

这是我的 POJO 模型类:

public class Partners extends ArrayList<String> {

@SerializedName("partners")
@Expose
public List<String> partners = new ArrayList<String>();

public List<String> getPartners() {
    return partners;
}

public void setName(List<String> partners) {
    this.partners = partners;
}

}

这是我的界面

public interface APIService {

        @GET("Partners")
        Call<Partners> getPartners();
}

这是我的 APIHelper 类

public class APIHelper {

    public static final String PARTNERS_URL = "https://part-of-link.com/partners.json/";

    public static APIService apiService;

    public static APIService getApiService() {
        if (apiService == null) {
            Retrofit retrofit = new Retrofit.Builder().baseUrl(PARTNERS_URL)
                    .addConverterFactory(GsonConverterFactory.create()).build();
            apiService = retrofit.create(APIService.class);
        }
        return apiService;
    }
}

这是片段,我有一个按钮,我想在其上实现onClick() 方法以从 API 获取数据并将其保存到合作伙伴表中。

public class DownloadMain extends Fragment implements Callback<Partners> {

    private Button dloadPartners;
    private Call<Partners> callPartners;
    public static APIService apiService;

    public DownloadMain() {}

    public DownloadMain newInstance() { return new DownloadMain(); }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.download_main, container, false);

        dloadPartners = (Button) view.findViewById(R.id.downloadPartners);
        dloadPartners.setOnClickListener(btnListener);

        callPartners = APIHelper.getApiService().getPartners();
        callPartners.enqueue(this);

        return view;
    }

    Button.OnClickListener btnListener = (new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            APIHelper helper = new APIHelper();
            apiService = helper.getApiService();

            Call<Partners> call = apiService.getPartners();
            call.enqueue(new Callback<Partners>() {
                @Override
                public void onResponse(Call<Partners> call, Response<Partners> response) {

        Call<Partners> call = apiService.getPartners();
        call.enqueue(new Callback<Partners>() {
            @Override
            public void onResponse(Call<Partners> call, Response<Partners> response) {

               List<String> partners =  response.body().getPartners();
                Log.d(TAG, "Number of partners received: " + partners.size());
                }

                @Override
                public void onFailure(Call<Partners> call, Throwable t) {
                    Toast.makeText(getActivity(), "FAIL!!!", Toast.LENGTH_SHORT).show();
                }
            });
        }
    });
    @Override
    public void onResponse(Call<Partners> call, Response<Partners> response) {


    }

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

    }
}

这里onResponse() 方法给我一个错误:Attempt to invoke virtual method 'java.util.List com.example...pojo.Partners.getPartners()' on a null object reference

我想要的是从网络上获取所有合作伙伴,并在单击按钮时将其保存到我的合作伙伴表中。

我找不到此错误的解决方案,因此如果有人可以帮助我,我将不胜感激。

问题:谁能指导我并告诉我出了什么问题并帮助我解决这个问题?

【问题讨论】:

  • JSON 响应的完整架构是什么?由于您使用 GSON 将 JSON 映射到 POJO,我怀疑您可能错误地声明了您的 POJO。
  • @crymson JSON 在我的 web api url 上看起来像这样 [ "partner1", "partner2", "partner3", ... , "partner150" ]
  • 我想指出的是,您连续两次调用您的 Retrofit 方法......而且您根本不需要 Partner 类

标签: java android nullpointerexception


【解决方案1】:

首先,Java 命名约定。 Partner 表示单个实体,而不是 Partners 的复数。 - 更改您的班级名称以反映这一点。这也让我们感到困惑,因为您的问题有两个同名的类。对于您的用例,不需要创建一个扩展 Arraylist 的类。


其次,请学习正确的 JSON 到 Java 的转换。您的 JSON 只是一个字符串数组 - 扩展 Arraylist 的对象再次是不必要的。

如果您想保留 ActiveAndroid 模型对象并将其用于 Retrofit,那么对于 List&lt;Partner&gt;,JSON 需要看起来像这样

[
   {"name": "partner1"},
   {"name": "partner2"} 
] 

对于当前使用内部 Arraylist 扩展 Arraylist 的 Partners 类,类似这样(这不是有效的 JSON)

[
  "partners" : [
      "partner1", 
      "partner2"
  ] 
] 

所以,再一次,您不需要扩展 Arraylist 的类。


最后,尝试了解 Retrofit 方法使用的“流程”。

你得到一个特定类型的Call对象,你enqueue它来启动HTTP请求,然后你定义一个Callback,它有两个动作用于请求成功和错误。

现在,您是否已经在 Fragment 上实现了回调?

public class DownloadMain extends Fragment implements Callback<Partners> 

但是您需要使用它 - 您在 Fragment 类的底部有 onResponseonError 这两个空方法... 那是你应该实现改造完成后发生的事情,这就是当你在onCreateView中有这一行时代码所在的地方@

callPartners.enqueue(this);

但是由于这些方法是空的,所以在该调用中什么也没有发生。同时,其他enqueue 方法有不必要的Callback 实现,而您可以只使用this

此外,没有冒犯,但您似乎只是在不知道发生了什么的情况下复制粘贴代码...注意您如何进行第二次不必要的 API 调用。

// Call 1
Call<Partners> call = apiService.getPartners();
call.enqueue(new Callback<Partners>() {
    @Override
    public void onResponse(Call<Partners> call, Response<Partners> response) {
        // Call 2, despite having a response 
        Call<Partners> call = apiService.getPartners();
        call.enqueue(new Callback<Partners>() {
            @Override
            public void onResponse(Call<Partners> call, Response<Partners> response) {

对于以上所有这些问题,我对Retrofit会出错并不感到惊讶,但是可以通过首先修复Retrofit Model来避免这个问题,然后在尝试使用它之前一定要检查response.body()是否为null .


如果你都做对了,onClick 中唯一的代码行,需要就是这个。

callPartners.enqueue(DownloadMain.this);

【讨论】:

  • 感谢您的回答。我已经完成了你所说的一切,但是在 onClick 方法中我在callPartners.enqueue(this); 上遇到错误并且无法弄清楚出了什么问题?
  • 我无法猜测该行可能发生的所有错误,那么该错误究竟说明了什么?
  • 这里是错误Error:(61, 25) error: method enqueue in interface Call&lt;T&gt; cannot be applied to given types; found: &lt;anonymous OnClickListener&gt;
  • 现在可以工作,但我在 onResponse 方法中犯了一些错误。需要解决这个问题
  • 我认为我的回答没有错误,所以如果现在一切正常,欢迎您接受答案。如果您仍然需要帮助,欢迎您创建另一个帖子。
【解决方案2】:

在按钮单击侦听器中,apiService 未初始化,尽管您正在调用 helper.getApiService();。所以 apiService 实例为空,当调用 Call call = apiService.getPartners();。因此 NullPointerException。

初始化 apiService。

@Override
public void onClick(View v) {
    APIHelper helper = new APIHelper();
    apiService = helper.getApiService();

    Call<Partners> call = apiService.getPartners();

【讨论】:

  • 它已初始化但无法正常工作..getting Attempt to invoke interface method 'int java.util.List.size()' on a null object reference
【解决方案3】:

似乎您的 JSON 响应只是一个字符串数组,所以我认为您可以取消 POJO,而是这样做:

public interface APIService {

    @GET("Partners")
    Call<List<String>> getPartners();
}

例如,在将您声明 Partners 的每个类型参数替换为 List&lt;String&gt; 时,将所有 Call&lt;Partners&gt; 替换为 Call&lt;List&lt;String&gt;&gt;

【讨论】:

  • 我已经像你说的那样做了,但现在我在这一行得到Attempt to invoke interface method 'int java.util.List.size()' on a null object reference`Log.d(TAG, "收到的合作伙伴数量:" + partners.size());`你知道可能是什么问题吗?
猜你喜欢
  • 2016-08-15
  • 1970-01-01
  • 2017-10-22
  • 1970-01-01
  • 1970-01-01
  • 2020-07-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多