Venjirai Venjirai - 3 months ago 26
Java Question

Callback Duplicate Code

I'm using okhttp3 with asynchronous callbacks to get JSONArrays/JSONObjects from the server and then parsing them and creating the particular object which is passed to the callback function.
Most of the callback code is the same for every method, but there are some lines of code that differ.
Is there a pattern that I can use to reduce the lines of code so that I don't have to write the same code over and over again for the different objects?
I marked the lines of code that differ for every method.
The problem I have is calling the particular JSON parsing function without using switch/case and varying the callback object.

//-----------------------differs-------------------------
public void getUser(final HTTPResponseCallback<User> callback)
{
//-----------------------differs-------------------------
final String url = domain + USERS;
//-------------------------------------------------------

okHttpClient.newCall(buildRequest(url)).enqueue(new Callback()
{
Handler handler = new Handler(Looper.getMainLooper());

@Override
public void onFailure(Call call, IOException e)
{
handler.post(new Runnable()
{
@Override
public void run()
{
callback.onFailure();
}
});
}

@Override
public void onResponse(Call call, final Response response) throws IOException
{
if (response.isSuccessful())
{
try
{
String responseBody = response.body().string();

//-----------------------differs-------------------------
JSONObject jsonResponse = new JSONObject(responseBody);
final User user = JsonParser.parseUser(jsonResponse
//------------------------------------------------------

handler.post(new Runnable()
{
@Override
public void run()
{
//---------------------------------------last parameter differs----------------------------------------------
callback.onSuccess(new HTTPTransaction(response.code(), response.message(), response.header("ETag")), user);
//-----------------------------------------------------------------------------------------------------------
}
});

}
catch (JSONException e)
{
...
}
}
else
...

}
}
}

Answer

1) Make in parameterized with <T> as type can differs:

public class CallBackWrapper<T> { 
    ...
    public void getUser(final HTTPResponseCallback<T> callback) { ...

2) Introduce callback object for unique parts which will return instance of type T:

interface Worker {
   T run(String responseBody);
}

public <T> void getUser(final HTTPResponseCallback<T> callback, Worker worker) { ...

3) Invoke needed worker:

                String responseBody = response.body().string();

                //-----------------------differs-------------------------
                final T obj = worker.run(responseBody);
                //------------------------------------------------------

                handler.post(new Runnable()
                {
                    @Override
                    public void run()
                    {
                        //---------------------------------------last parameter differs----------------------------------------------
                        callback.onSuccess(new HTTPTransaction(response.code(), response.message(), response.header("ETag")), obj);
                        //-----------------------------------------------------------------------------------------------------------
                    }
                });