改造 onResponse 方法不起作用,抛出 NullPointerException [英] Retrofit onResponse method not working, throws NullPointerException

查看:60
本文介绍了改造 onResponse 方法不起作用,抛出 NullPointerException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

我的 JSON 看起来像这样

<预><代码> ["合作伙伴1","合作伙伴2","合作伙伴3",... ,合作伙伴150"]

我有 Table 合作伙伴 (ActiveAndroid),我想在其中保存 API 中的所有合作伙伴.

@Table(name = "Partners")公共类合作伙伴扩展模型{@Column(name = "姓名")字符串名称;公共合作伙伴() {}公共合作伙伴(字符串名称){this.name = 名称;}}

这是我的 POJO 模型类:

public class Partners extends ArrayList{@SerializedName("合作伙伴")@暴露公共列表<字符串>合作伙伴 = 新的 ArrayList();公共列表<字符串>获取合作伙伴(){返回合作伙伴;}公共无效集名称(列表<字符串>合作伙伴){this.partners = 合作伙伴;}

}

这是我的界面

公共接口 APIService {@GET("合作伙伴")致电<合作伙伴>getPartners();}

这是我的 APIHelper 类

公共类 APIHelper {public static final String PARTNERS_URL = "https://part-of-link.com/partners.json/";公共静态 APIService apiService;公共静态 APIService getApiService() {如果(apiService == null){改造改造 = new Retrofit.Builder().baseUrl(PARTNERS_URL).addConverterFactory(GsonConverterFactory.create()).build();apiService = retrofit.create(APIService.class);}返回 apiService;}}

这是 Fragment,我有一个按钮,我想在上面实现 onClick() 方法以从 API 获取数据并将其保存到 Partners 表中.

public class DownloadMain extends Fragment implements Callback{私人按钮 dloadPartners;私人电话<合作伙伴>呼叫合作伙伴;公共静态 APIService apiService;公共 DownloadMain() {}public DownloadMain newInstance() { return new DownloadMain();}@覆盖public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);}@覆盖公共视图 onCreateView(LayoutInflater inflater, ViewGroup 容器,捆绑savedInstanceState) {查看视图 = 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);返回视图;}Button.OnClickListener btnListener = (new View.OnClickListener() {@覆盖public void onClick(View v) {APIHelper helper = new APIHelper();apiService = helper.getApiService();致电<合作伙伴>调用 = apiService.getPartners();call.enqueue(new Callback() {@覆盖public void onResponse(Call call, Response response) {致电<合作伙伴>调用 = apiService.getPartners();call.enqueue(new Callback() {@覆盖public void onResponse(Call call, Response response) {列表<字符串>合作伙伴 = response.body().getPartners();Log.d(TAG, "收到的合作伙伴数量:" + partners.size());}@覆盖public void onFailure(Call call, Throwable t) {Toast.makeText(getActivity(), "FAIL!!!", Toast.LENGTH_SHORT).show();}});}});@覆盖public void onResponse(Call call, Response response) {}@覆盖public void onFailure(Call call, Throwable t) {}}

这里 onResponse() 方法抛出一个错误:Attempt to invoke virtual method 'java.util.List com.example...pojo.Partners.getPartners()' on空对象引用

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

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

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

解决方案

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

<小时>

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

如果您想保留 ActiveAndroid 模型对象并将其用于 Retrofit,则 List

的 JSON 需要如下所示<预><代码>[{"name": "partner1"},{"name": "partner2"}]

对于当前的 Partners 类,它扩展了一个带有内部 Arraylist 的 Arraylist,类似这样(不是有效的 JSON)

<预><代码>[伙伴" : ["合作伙伴1",伙伴2"]]

同样,您不需要扩展 Arraylist 的类.

<小时>

最后,尝试理解 Retrofit 方法使用的流程".

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

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

public class DownloadMain extends Fragment implements Callback

但是你需要使用它 - 你在 Fragment 类的底部有 onResponseonError 的两个空方法... 那是你应该在 Retrofit 完成后实现什么的地方,这就是当你在 onCreateView

中有这行代码的地方

callPartners.enqueue(this);

但是由于这些方法是空的,所以在那个调用中什么也没有发生.同时其他 enqueue 方法有不必要的 Callback 实现,当你可以使用 this

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

//调用 1致电<合作伙伴>调用 = apiService.getPartners();call.enqueue(new Callback() {@覆盖public void onResponse(Call call, Response response) {//调用 2,尽管有响应致电<合作伙伴>调用 = apiService.getPartners();call.enqueue(new Callback() {@覆盖public void onResponse(Call call, Response response) {

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

<小时>

如果你做的都正确,onClick 中唯一的一行代码就是这个.

callPartners.enqueue(DownloadMain.this);

I'm trying to get data from web API, but something is wrong in my onResponse() method and I can't figure it out.

My JSON looks like this

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

I have Table partners (ActiveAndroid) in which I would like to save all partners from the API.

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

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

    public Partners() {}

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

Here is my POJO model class:

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;
}

}

This is my interface

public interface APIService {

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

This is my APIHelper class

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;
    }
}

And this is Fragment where I have a Button on which I would like to implement thw onClick() method to get the data from the API and save it into the Partners table.

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) {

    }
}

Here the onResponse() method throws me an error: Attempt to invoke virtual method 'java.util.List com.example...pojo.Partners.getPartners()' on a null object reference

What I want is to get all partners from web and save it into my Partners table on button click.

I can't find solution to this error so if someone could help me I've would be grateful.

Question: Could anybody guide me and tell me what is wrong and help me to fix this?

解决方案

Firstly, Java naming conventions. Partner represents a single entity, not plural of Partners. - Change your classname to reflect that. It's also confusing for us because your question has two classes of the same name. For your use case, making a class that extends an Arraylist is unnecessary.


Secondly, please learn proper JSON-to-Java conversions. Your JSON is simply an Array of Strings - the object extending the Arraylist is again unnecessary.

If you want to keep the ActiveAndroid model object and use it for Retrofit, the JSON needs to look like this for a List<Partner>

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

And for the current Partners class that extends an Arraylist with an inner Arraylist, something like this (which isn't valid JSON)

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

So, again, you don't need the class that extends the Arraylist.


And finally, try to understand the "flow" of a Retrofit method usage.

You get a Call object of a certain type, you enqueue it to start the HTTP request, then you define a Callback with two actions for when the request succeeds and errors.

Now, see that you've implemented the Callback on the Fragment?

public class DownloadMain extends Fragment implements Callback<Partners> 

But you need to use that - you have those two empty methods for onResponse and onError at the bottom of the Fragment class... That's where you should implement what happens when Retrofit is done, and that's where the code goes when you have this line in onCreateView

callPartners.enqueue(this);

But since those methods are empty, nothing happens on that call. Meanwhile the other enqueue methods have unnecessary Callback implementations, when you could just use this

Additionally, no offense, but you seem to just be copy-pasting code around without knowing what's happening... Notice how you make a second, unnecessary API call.

// 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) {

With all these above problems, I'm not too surprised Retrofit would error out, but the problem can be avoided by first fixing the Retrofit Model, then be sure to check if response.body() is null before you attempt to use it.


If you do it all correctly, the only line of code in the onClick, needs to just be this.

callPartners.enqueue(DownloadMain.this);

这篇关于改造 onResponse 方法不起作用,抛出 NullPointerException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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