Search code examples
javaandroidokhttpandroid-mvp

How to design a class that can pass data from server when data is finish downloading


I'm new on Android development and I'm learning how to use MVP pattern correctly in recently.

Now I'm facing a tricky problem, hope can get some helpful suggestion or solution from here.

First, here is my presenter

public class MVPPresenter {

    private MVPView mvpView;

    public MVPPresenter(MVPView mvpView) {
        this.mvpView = mvpView;
    }

    public void loadData() {
        mvpView.startLoading();
        final List<MVPModel> list = new ArrayList<>();
        //the part that I trying to extract starts here.
        Call call = DataRetriever.getDataByGet(URLCombiner.GET_FRONT_PAGE_ITEMS);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                mvpView.errorLoading();
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful()) {
                    try {
                        JSONObject result = new JSONObject(response.body().string());
                        int errorCode = result.getInt("ErrorCode");
                        if (errorCode == 0) {
                            JSONArray value = result.getJSONObject("Value").getJSONArray("hot");
                            for (int i = 0; i < value.length(); i++) {
                                MVPModel mvpModel = new MVPModel();
                                String name = null;
                                String image = null;
                                try {
                                    name = value.getJSONObject(i).getString("title");
                                    image = URLCombiner.IP + value.getJSONObject(i).getString("pic");
                                } catch (JSONException e) {
                                    e.printStackTrace();
                                }
                                mvpModel.setName(name);
                                mvpModel.setImage(image);
                                list.add(mvpModel);
                            }
                            if (list.size() > 0) {
                                mvpView.successLoading(list);
                                mvpView.finishLoading();
                            } else {
                                mvpView.errorLoading();
                            }
                        } else {
                            mvpView.errorLoading();
                        }
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                } else {
                    mvpView.errorLoading();
                }
            }
        });
        //the part that I trying to extract ends here.
    }
}

As you can see, I'm trying to extract the part which is using OKHttp libs into a class (I call it data manager) which I hope it can handle every task between server and client. But here's the thing, when I trying to pass the result from the data manager to presenter, I got NullPointException because of the async mechanism.

I would like to know how to passing the data, which is come from server in async, to the presenter when the data has finish downloading.

And here's my ideal data manager, I know this might looks stupid but I think this can make my problem more clearly.

public class LoadServerData {

    private static JSONArray arrayData = new JSONArray();

    public static JSONArray getServerData() {
        Call call = DataRetriever.getDataByGet(URLCombiner.GET_FRONT_PAGE_ITEMS);
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful()) {
                    try {
                        JSONObject result = new JSONObject(response.body().string());
                        int errorCode = result.getInt("ErrorCode");
                        if (errorCode == 0) {
                            arrayData = result.getJSONObject("Value").getJSONArray("hot");  //the data I would like to return.
                        }
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        return arrayData;   //this is gonna be an empty data.
    }
}

I've reading some article that might can solve my problem, but still not getting any fine answer. Perhaps I've using wrong keyword I think. Hopes you guys can give me some ideas or solutions to help me or inspire me.

P.S. version of OKhttp libs is 3.7.0


Solution

  • Create a simple Listener so it can be called whenever the server call finishes:

    public class LoadServerData {
    
        public static interface Listener {
            public void onSuccess(JSONArray data);
            public void onError(Exception error);
        }
    
        public static void getServerData(Listener listener) {
            Call call = DataRetriever.getDataByGet(URLCombiner.GET_FRONT_PAGE_ITEMS);
            call.enqueue(new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    listener.onError(e);
                }
    
                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    if (response.isSuccessful()) {
                        try {
                            JSONObject result = new JSONObject(response.body().string());
                            int errorCode = result.getInt("ErrorCode");
                            if (errorCode == 0) {
                                JSONArray arrayData = result.getJSONObject("Value").getJSONArray("hot");  //the data I would like to return.
                                listener.onSuccess(arrayData);
                            } else {
                                listener.onError(...);
                            }
                        } catch (JSONException e) {
                            e.printStackTrace();
                            listener.onError(e);
                        }
                    } else {
                        listener.onError(...);
                    }
                }
            });
        }
    }