改进onResponse方法不起作用,抛出NullPointerException

时间:2016-08-18 20:32:47

标签: java android nullpointerexception

我正在尝试从网络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;
    }
}

这就是Fragment,我有一个Button,我想用它来实现onClick()方法来从API获取数据并将其保存到Partners表中。

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

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

我无法找到解决此错误的方法,所以如果有人能帮助我,我会感激不尽。

问题:有人可以指导我并告诉我有什么问题并帮我解决这个问题吗?

3 个答案:

答案 0 :(得分:1)

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

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

如果要保留ActiveAndroid模型对象并将其用于Retrofit,则JSON需要看起来像List<Partner>

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

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

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

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

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

您获得某个类型的Call对象,您enqueue启动HTTP请求,然后定义Callback,其中包含两个请求,用于请求成功和错误。

现在,看到你在Fragment上实现了Callback?

public class DownloadMain extends Fragment implements Callback<Partners> 

但你需要使用 - 你在Fragment类的底部有onResponseonError这两个空方法... 那是< / em>你应该在哪里实现Retrofit完成后会发生的事情,当你在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);

答案 1 :(得分:0)

在按钮单击侦听器中,虽然您正在调用helper.getApiService();,但未初始化apiService。因此,当调用Call call = apiService.getPartners();时,apiService实例为null。因此NullPointerException。

初始化apiService。

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

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

答案 2 :(得分:0)

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

public interface APIService {

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

在替换您使用Partners声明List<String>的每个类型参数时,将所有Call<Partners>替换为Call<List<String>>