Darksymphony
Darksymphony

Reputation: 2693

Android retrofit how to show No data message when empty json array

I am using retrofit to retrieve data from my server - it is a user search:

        ApiInterface apiService = ApiClient.getClient().create(ApiInterface.class);
    Call<List<Movie>> call = apiService.getSearch(lng, 0, newText);

    call.enqueue(new Callback<List<Movie>>() {

        @Override
        public void onResponse(@NonNull Call<List<Movie>> call, @NonNull Response<List<Movie>> response) {
            
            movieList = response.body();
            if (dialog != null) {
                dialog.dismiss();  dialog = null;
            }

            if (response.isSuccessful()) {
                recyclerAdapter.setMovieList(movieList);
            } else {

                showMsgSnack(getString(R.string.Nodata));
            }

        }

        @Override
        public void onFailure(@NonNull Call<List<Movie>> call, @NonNull Throwable t) {
            if (dialog != null) {
                dialog.dismiss();  dialog = null;
            }

            if(t instanceof UnknownHostException){

                showMsgSnack(getString(R.string.Network));
            }

            else if(t instanceof SocketTimeoutException){
                showMsgSnack(getString(R.string.ServerTimeout));
            }

            else {
                showMsgSnack(getString(R.string.ServerError));
            }
        }
    });

Json is generaed via PHP in the server. If the search is success, json will return like [{"title": "sometitle",...}].

But if there is no match in database, I am returning just an empty {}.

But in android it goes to the failure and shows ServerError message. I want to show in that case some message as No match found.

How can I handle this response?

I also created a Default callback for Nullpointerexception, but this still doesn't work:

        call.enqueue(new DefaultCallback<>(new Callback<List<Movie>>() {

        @Override
        public void onResponse(@NonNull Call<List<Movie>> call, @NonNull Response<List<Movie>> response) {

            movieList = response.body();
            if (dialog != null) {
                dialog.dismiss();
                dialog = null;
            }

            if (response.isSuccessful()) {
                recyclerAdapter.setMovieList(movieList);
            } else {

                showMsgSnack(getString(R.string.Nodata));
            }
        }

        @Override
        public void onFailure(@NonNull Call<List<Movie>> call, @NonNull Throwable t) {
            if (dialog != null) {
                dialog.dismiss();
                dialog = null;
            }

            if (t instanceof UnknownHostException) {

                showMsgSnack(getString(R.string.Network));
            }

            if (t instanceof NullPointerException) {

                showMsgSnack(getString(R.string.Nodata));
            } else if (t instanceof SocketTimeoutException) {
                showMsgSnack(getString(R.string.ServerTimeout));
            } else {
                showMsgSnack(getString(R.string.ServerError));
            }

        }
    }));
}

public static class DefaultCallback<T> implements Callback<T> {

    private static final String TAG = "YOUR_TAG";
    private final Callback<T> callback;

    public DefaultCallback(Callback<T> callback) {
        this.callback = callback;
    }

    @Override
    public void onResponse(@NonNull Call<T> call, Response<T> response) {
        if (response.body() == null) {
            callback.onFailure(call, new NullPointerException("Empty response"));
        } else {
            callback.onResponse(call, response);
        }
    }

    @Override
    public void onFailure(@NonNull Call<T> call, Throwable t) {
        Log.e(TAG, t.toString());
        callback.onFailure(call, t);
    }
}

It says: YOUR_TAG: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 2 path $

Upvotes: 0

Views: 198

Answers (1)

piyushpk
piyushpk

Reputation: 91

In android after receiving response from API you want List of type Movie object (List) which is like [{"title": "sometitle",...}] this.

But when you don't find anything on search then you are returning " {} "

And here you are getting an issue, this is because you are excepting List means Array and API returning "{}" means Object.

Simple solution don't send object "{}" send Array "[]" and check

@Override
    public void onResponse(@NonNull Call<List<Movie>> call, @NonNull Response<List<Movie>> response) {

        movieList = response.body();
        if (dialog != null) {
            dialog.dismiss();
            dialog = null;
        }

        if (movieList.size() > 0) {
            recyclerAdapter.setMovieList(movieList);
        } else {
            showMsgSnack(getString(R.string.Nodata));
        }
    }

Hope you understand and this will help!

Upvotes: 1

Related Questions