Невозможно получить данные из веб-сервиса с помощью Retrofit - PullRequest
0 голосов
/ 29 мая 2020

Я пытаюсь загрузить очень простые данные в формате JSON, сгенерированные веб-сервисом, используя Retrofit и Gson, а также пытаюсь реализовать архитектуру MVVM, но получаю null значение при вызове данных из ViewModel: я видел много SO-вопросов (или, может быть, не так много), но не могу понять, где и почему у меня возникают эти проблемы.

Итак, что я имеет это

JSON ОТВЕТ : Это может быть либо это:

{
    "ok": [
        {
            "id": 1,
            "username": "test1",
            "pass": "123",
            "reg_date": "2020-05-20 00:00:00"
        }
    ]
}

, либо это:

{
    "error": [
        {
            "message":"user doesn't exists"
        }
    ]
}

I ' Мы создали соответствующие POJO для каждого типа ответа, которые я опущу для простоты. Но также я создал общий c POJO для обработки ответа (спасибо @ Công Hải)

** POJOGenericResponse. java*

public class POJOGenericResponse{
    @SerializedName("ok")
    private LiveData<ArrayList<POJOUsr>> user;
    @SerializedName("error")
    private LiveData<ArrayList<POJOError>> error;

    //Constructor and Getters...
}

JsonApi. java

public interface JsonApi {
    @GET("SelectAllUsr.php")
    Call<LiveData<POJOGenericResponse>> getGenericResponse();
}

Я не знаю, как следует называть этот класс в соответствии с его назначением и соглашениями об именах

RetrofitInstance. java

public class RetrofitInstance {
    private static String URL_BASE = "http://192.168.0.35/app_android/webservices/";
    private static Retrofit retrofit;
    private static Gson gson;

    public Retrofit getRetrofitInstance(){
        gson = new GsonBuilder().setLenient().create();
        if(retrofit == null){
            retrofit = new Retrofit.Builder()
                    .baseUrl(URL_BASE)
                    .addConverterFactory(GsonConverterFactory.create(gson))
                    .build();
        }
        return retrofit;
    }
}

LoginRepository. java

public class LoginRepository{
    private RetrofitInstance retrofitInstance;
    private JsonApi jsonApi;
    private LiveData<POJOGenericResponse> genericResponse;
    private Call<LiveData<POJOGenericResponse>> call;

    public LoginRepository() {
        retrofitInstance = new RetrofitInstance();
        jsonApi = retrofitInstance.getRetrofitInstance().create(JsonApi.class);
        call = jsonApi.getRespuestaGenerica();
    }

    //TODO: This should be done in another class??
    public LiveData<POJOGenericResponse> getGenericResponse() {
        call.clone().enqueue(new Callback<LiveData<POJOGenericResponse>>() {

            @Override
            public void onResponse(Call<LiveData<POJOGenericResponse>> call, Response<LiveData<POJOGenericResponse>> response) {
                if (response.isSuccessful()) {
                    genericResponse= response.body();
                } else {
                    //
                }
            }

            @Override
            public void onFailure(Call<LiveData<POJOGenericResponse>> call, Throwable t) {
                //
            }
        });
        return genericResponse;
    }
}

LoginViewModel. java

public class LoginViewModel extends AndroidViewModel {
    private RepositorioLogin loginRepository;
    private MutableLiveData<POJOGenericResponse> serverResponse;

    public ViewModelLogin(@NonNull Application application) {
        super(application);
        loginRepository = new RepositorioLogin();
        serverResponse = new MutableLiveData<>();
    }

    public void setServerResponse(){
        serverResponse.setValue(loginRepository.getGenericResponse().getValue());
    }

    public LiveData<POJORespuestaGenerica> getServerResponse(){
        return serverResponse;
    }
}

Здесь должны отображаться данные

FragmentData. java

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_data, container, false);
        TextView exampleText = v.findViewById(R.id.tv_test);

        LoginViewModel loginViewModel = new ViewModelProvider(requireActivity()).get(LoginViewModel.class);
        loginViewModel.getServerResponse().observe(requireActivity(), new Observer<POJORespuestaGenerica>() {
            @Override
            public void onChanged(POJOGenericResponse pojoGenericResponse) {
                if (pojoGenericResponse.getUser() != null) {
                    exampleText.setText(pojoGenericResponse.getUser().getValue().get(0).getUsername());
                }
                if (pojoGenericResponse.getError() != null) {
                    exampleText.setText(pojoGenericResponse.getError().getValue().get(0).getMensaje());
                }
            }
        });

При отладке я получаю ошибку

response = Не удается найти локальную переменную 'response' serverResponse.setValue (loginRepository.getGenericResponse (). GetValue ()); \ n = java .lang.NullPointerException response = Не удается найти локальную переменную 'response'

, которые описывают проблему сами по себе, но не могут ее решить.

Также любые рекомендации по реализации архитектуры MVVM будет очень признателен.

Заранее большое спасибо

1 Ответ

1 голос
/ 29 мая 2020

Похоже, это неправильный бит -

public LiveData<POJOGenericResponse> getGenericResponse() {
        call.clone().enqueue(new Callback<LiveData<POJOGenericResponse>>() {

            @Override
            public void onResponse(Call<LiveData<POJOGenericResponse>> call, Response<LiveData<POJOGenericResponse>> response) {
                if (response.isSuccessful()) {
                    genericResponse= response.body();
                } else {
                    //
                }
            }

            @Override
            public void onFailure(Call<LiveData<POJOGenericResponse>> call, Throwable t) {
                //
            }
        });
        return genericResponse;
    }

Итак, onResponse - это асинхронный вызов, и вы немедленно возвращаете return genericResponse; из метода.

Вместо получение возврата из этого метода измените его на void и непосредственно наблюдайте на private LiveData<POJOGenericResponse> genericResponse;

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...