MahmoudTarek MahmoudTarek - 3 months ago 12
Android Question

I have two methods inside each other, how to return to parent from inner method

I have this CustomRequest class:

public class CustomRequest extends Request<JSONObject>{

private Listener<JSONObject> listener;
private Map<String, String> params;

public CustomRequest(String url, Map<String, String> params,
Listener<JSONObject> reponseListener, ErrorListener errorListener) {
super(Method.GET, url, errorListener);
this.listener = reponseListener;
this.params = params;
}

public CustomRequest(int method, String url, Map<String, String> params,
Listener<JSONObject> reponseListener, ErrorListener errorListener) {
super(method, url, errorListener);
this.listener = reponseListener;
this.params = params;
}

@Override
protected Map<String, String> getParams() throws com.android.volley.AuthFailureError {
return params;
};

@Override
protected void deliverResponse(JSONObject response) {
listener.onResponse(response);
}

@Override
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
try {
String jsonString = new String(response.data,
HttpHeaderParser.parseCharset(response.headers));
return Response.success(new JSONObject(jsonString),
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JSONException je) {
return Response.error(new ParseError(je));
}
}


}

And then I have my class JSONRequest:

public class JSONRequest extends AppCompatActivity{
public String url = "http://192.168.1.101/apps/clients/service.php";
public Map<String, String> requestParameters;

public void setParameters(Map<String, String> Parameters) {
this.requestParameters = Parameters;
}

public JSONObject postRequest() {
CustomRequest jsonObjectRequest = new CustomRequest(Request.Method.GET, this.url, this.requestParameters, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
try {
return response;
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e("Error", error.getMessage());
}
});
jsonObjectRequest.setRetryPolicy(new DefaultRetryPolicy(20 * 1000, 1, 1.0f));

ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null && activeNetwork.isConnectedOrConnecting();

if (isConnected) {
AppController.getInstance().addToRequestQueue(jsonObjectRequest);
} else {
Toast.makeText(getApplicationContext(), "You need internet connection to perform this", Toast.LENGTH_LONG).show();
}
}


}

What I want to do is inside my postRequest method, there's an object of CustomRequest class called jsonObjectRequest, I want to return the JSONObject response variable from the onResponse method to the parent postRequest method, I get an error at:

return response;


because it tells me that the method's return type is void, please tell me what am I doing wrong and what is the correct way.

I'm supposing to use my class as the following:

JSONRequest request = new JSONRequest();
request.setParameters(Parameters);
JSONObject result = request.postRequest();


Thanks in advance

Answer

it tells me that the method's return type is void,

Yes, that's how most callbacks are defined. There is often no need to return, you instead act on the result.

I want to return the JSONObject response variable from the onResponse method to the parent postRequest method

Again, there's no need to return anything if you restructure the call. Plus, there was no return statement at the end of the method, so your code wasn't completely correct to start.

Use Volley to your advantage and pass around its Listener objects in order to "return things".

Sidenote This doesn't / shouldn't be an Activity class. If you need a Context, make a constructor.

public class JSONRequestService {

    private final Context mContext;  // TODO: Make constructor 

    final Response.ErrorListener errorListener = new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            Log.e("Error", error.getMessage());
        };

    // passthough a callback instead of returning 
    public void postRequest(Response.Listener<JSONObject> listener) {
        CustomRequest jsonObjectRequest = new CustomRequest(Request.Method.GET, this.url, requestParameters, listener, errorListener);

        // TODO: Add to request queue 

    } 
} 

Then, to use

JSONRequestService service = new JSONRequestService(getApplicationContext());
service.setParameters(Parameters);
service.postRequest(new Response.Listener<JSONObject>() {
    @Override
    public void onResponse(JSONObject response) {
        try {
            //  response is now available where you want 
        } catch (JSONException e) {
            e.printStackTrace();
        }
    });

Now, as you can see, there's really not much difference between this approach and just making the Volley request directly. All you've done is expose the parameters and hide the URL, RequestQueue, and error listener behind another class.

I might even suggest using a Builder Pattern approach for the parameters because certainly each request uses different parameters.

public JSONRequestService withParameters(Map<String, String> Parameters) {
    this.requestParameters = Parameters;
    return this;
}

And now, you get to collapse the setter with the execution

JSONRequestService service = new JSONRequestService(getApplicationContext());

service.withParameters(Parameters).postRequest();