A
A
Al2016-08-22 23:10:12
Java
Al, 2016-08-22 23:10:12

How to properly implement callback in java?

I recently started to study Android and java itself , before that I always wrote in nodeJS , and for a long time I got very used to js .
And so, in the process of studying, the moment came when I decided to write one single class that would send requests, and as a result of an error or success, it would execute the corresponding methods of the class from which we send this request.
There is a MainActivity class in which, by clicking on the button, we send a request to the server and insert the response into the TextView . Now I have implemented the callbacks like this:

public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {

protected void onCreate(Bundle savedInstanceState) {


sendButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                DoRequestClass doRequestClass = new DoRequestClass(){

                    @Override
                    public void onOK(JSONObject response) {
                        successReq(response);
                    }

                    @Override
                    public void onError(VolleyError error) {
                        errorReq(error);
                    }
                };
            doRequestClass.execute("http://myserver.local", MainActivity.this);
        }
    });


public void successReq(JSONObject response){
    txtDisplay.setText("Response => "+response.toString());
}

public void errorReq(VolleyError error){
    txtDisplay.setText("Error => "+error.toString());
}

// other methods

Such is the abstract class DoRequestClass for the test
public abstract class DoRequestClass implements DoRequestInterface {

    @Override
    public void execute(String url, Context context) {
        RequestQueue queue = Volley.newRequestQueue(context);

        JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {

            @Override
            public void onResponse(JSONObject response) {
                DoRequestClass.this.onOK(response);
            }

        }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
                DoRequestClass.this.onError(error);
            }

        });

        queue.add(jsObjRequest);
    }
}

With interface DoRequestInterface
interface DoRequestInterface {
    void execute(String url, Context context);

    void onOK(JSONObject response);

    void onError(VolleyError error);
}

Everything described above works, but is it possible to somehow pass successReq and errorReq to DoRequestClass in such a way as we would do it in javascript, about what I mean, about the desired result, see how I would like them to be passed approximately:
sendButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                DoRequestClass doRequestClass = new DoRequestClass();
                doRequestClass.setSuccessCallback(successReq);
                doRequestClass.setErrorCallback(errorReq);
                doRequestClass.execute("http://lessons.flexiblejs.ru/test.php", MainActivity.this);
            }
        });

As you understood from the code above, setSuccessCallback and setErrorCallback are methods that will tell the DoRequestClass class which methods of the MainActivity class should be executed after a successful or unsuccessful request.
This or similar would work fine in javascript, but such java code will not work. The question is how to create something like this or close to it? And is it even possible? The bottom line is not to write extra code and create extra type methods as in my working example onOK and onError .
I ask you, if possible, to give the most detailed answer with explanations, because. my knowledge of java is not great at all.

Answer the question

In order to leave comments, you need to log in

3 answer(s)
V
Vladimir Yakushev, 2016-08-23
@Sanu0074

Callback must be implemented as a separate interface and say that our activity implements this interface. As a result, we simply pass a link to our activity in DoRequestInterface. And in the activity we implement the necessary two methods for Callback. To avoid leaks, I recommend wrapping the callback in a soft link.

interface DoRequestInterface {
    void execute(String url, DoRequesCallback callback);
}

interface DoRequesCallback {
    void successReq(JSONObject response);
    void errorReq(VolleyError error);
}

public abstract class DoRequestClass implements DoRequestInterface {
  @Override
  public void execute(String url, DoRequesCallback callback) {
      RequestQueue queue = Volley.newRequestQueue(context);
      final WeakReference<DoRequesCallback> weakCallback = new WeakReference<DoRequesCallback>(callback);
      JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
          @Override
          public void onResponse(JSONObject response) {
              DoRequesCallback callback = weakCallback.get();
              if (callback != null) {
              	callback.successReq(response);
              }
          }
      }, new Response.ErrorListener() {
          @Override
          public void onErrorResponse(VolleyError error) {
            DoRequesCallback callback = weakCallback.get();
            if (callback != null) {
            	callback.errorReq(error);
            }
          }

      });
      queue.add(jsObjRequest);
  }
}

public class MainActivity extends AppCompatActivity implements DoRequesCallback {
  
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    sendButton.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v) {
          	DoRequestClass doRequestClass = new DoRequestClass();
            doRequestClass.execute("http://myserver.local", this);
          }
      });
  }

  @Override
  public void successReq(JSONObject response){
      txtDisplay.setText("Response => "+response.toString());
  }

  @Override
  public void errorReq(VolleyError error){
      txtDisplay.setText("Error => "+error.toString());
  }
}

A
Alexey Cheremisin, 2016-08-22
@leahch

The observer design pattern will help you - https://ru.m.wikipedia.org/wiki/Observer_(pattern...
See implementation in java.

I
ipc_ngs, 2016-08-22
@ipc_ngs

To pass methods as parameters, you can use lambdas and method references in Java8, see https://habrahabr.ru/post/224593/

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question