2016-08-18 2 views
-2

Я пытаюсь получить данные из веб-API, но что-то не так в моем методе onResponse(), и я не могу понять это.Retrofit onResponse метод не работает, throws NullPointerException

Моей JSON выглядит так

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

У меня есть партнеры таблицы (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; 
    } 
} 

И это Фрагмент, где у меня есть кнопка, на которой я хотел бы реализовать метод thw 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

То, что я хочу, чтобы получить все партнеры из Интернета и сохранить его в моей таблице партнеры по нажатию кнопки.

Я не могу найти решение этой ошибки, так что если кто-то может мне помочь, я был бы признателен.

Вопрос: Может ли кто-нибудь руководить мной и рассказывать мне, что не так, и помочь мне исправить это?

+0

Какова полная схема ответа JSON? Поскольку вы используете GSON для сопоставления JSON с POJO, я подозреваю, что вы, возможно, неправильно указали свой POJO. – crymson

+0

@crymson JSON на моем веб-апи URL выглядит следующим образом '[ "Partner1", "партнера 2", "partner3", ... "partner150" ]' – RubyDigger19

+0

Я просто хотел бы отметить, что вы дважды вызываете метод Retrofit дважды ... И вам совсем не нужен партнерский класс –

ответ

1

Во-первых, соглашения об именах Java. Partner представляет собой единое целое, а не множественное число Partners. - Измените свое имя класса, чтобы это отразить. Это также путает нас, потому что ваш вопрос имеет два класса с одним и тем же именем. Для вашего случая использования класс, который расширяет Arraylist, не нужен.


Во-вторых, изучите правильные преобразования JSON-to-Java. Ваш JSON - это просто массив строк - объект, расширяющий Arraylist, снова не нужен.

Если вы хотите сохранить объект ActiveAndroid модели и использовать его для модернизации, то JSON должен выглядеть для List<Partner>

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

И для текущего Partners класса, который расширяет Список_массивы с внутренним Arraylist , что-то вроде этого (который не является действительным JSON)

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

Итак, опять же, вам не нужен класс, который расширяет Список_массивов.

И, наконец, попытайтесь понять «поток» использования метода «Дооснащение».

Вы получаете Call объект определенного типа, вы enqueue его, чтобы начать запрос HTTP, то вы определяете Callback с два действия для того, когда запрос выполняется успешно и ошибок.

Теперь вы видите, что вы внедрили обратный вызов на фрагменте?

public class DownloadMain extends Fragment implements Callback<Partners> 

Но вы должны использования, - у вас есть эти два пустых методов onResponse и onError в нижней части класса фрагмента ... Это где вы должны осуществить то, что происходит, когда Переоборудование делается, и вот где код идет, когда у вас есть эта линия в 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) { 

С учетом всех этих вышеперечисленных проблем, я не слишком удивлен дооснащения бы без ошибок, но проблемы можно избежать с помощью первой фиксации Дооснащаемый модели, то не забудьте проверить, если response.body() является недействительным, прежде чем пытаться используй это.


Если вы все сделаете правильно, единственная строка кода в onClick должна быть именно такой.

callPartners.enqueue(DownloadMain.this); 
+0

Спасибо за ваш ответ. Я сделал все, что вы сказали, но в методе onClick я получаю ошибку на 'callPartners.enqueue (this);' и не может понять, что не так? – RubyDigger19

+0

Я не могу догадаться об ошибках, которые могут произойти в этой строке, и что именно говорит об ошибке? –

+0

вот ошибка 'Ошибка: (61, 25) error: метод enqueue в интерфейсе Call не может быть применен к заданным типам; найдено: ' – RubyDigger19

0

В прослушивателе нажатия кнопки apiService не инициализируется, хотя вы вызываете helper.getApiService() ;. Таким образом, экземпляр apiService имеет значение null при вызове Call call = apiService.getPartners() ;. следовательно, NullPointerException.

Инициализировать apiService.

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

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

Он инициализирован, но не работает..getting «Попытка вызвать метод интерфейса» int java.util.List.size() 'в ссылке нулевого объекта. – RubyDigger19

0

Похоже, ваш ответ JSON это просто массив строк, так что я думаю, что вы можете сделать прочь с POJOs и вместо того, чтобы сделать это:

public interface APIService { 

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

, заменяя каждый параметр типа, где вы объявили Partners с List<String>, например, заменить все Call<Partners> на Call<List<String>>

+0

Я сделал, как вы сказали, но теперь я получаю 'Попытка вызвать метод интерфейса' int java.util.List.size() 'в ссылке нулевого объекта' this this line 'Log.d (TAG,« Количество полученных партнеров: »+ partners.size());« Знаете ли вы, может быть, в чем проблема? – RubyDigger19

Смежные вопросы