Tengo 3 clases: LogIn, Logic Controller y Web Service.

LogIn es una actividad que, al presionar un botón, ejecuta un método LogicController estático que, a su vez, ejecuta un método estático en WebService. WebService realiza una solicitud al servidor mediante JsonObjectRequest. Necesito esa interacción para representar el modelo MVC (un trabajo escolar lo requiere), y no podría hacerlo sin métodos estáticos, ya que no podría "serializar" LogicController para pasarlo como una variable a LogIn.

El problema es que no puedo hacer que LogIn espere a que Web Service complete su trabajo antes de continuar, y lo necesito para usar un parámetro devuelto por él.

Clase de inicio de sesión:

public class LogIn extends AppCompatActivity {
    EditText txtUsr;
    EditText txtPass;
    Button btnLogIn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        txtUsr = (EditText) findViewById(R.id.txtUsr);
        txtPass = (EditText) findViewById(R.id.txtPass);

        btnLogIn = (Button) findViewById(R.id.btnIS);
        btnLogIn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                logInWebService();
            }
        });
    }

    private void logInWebService() {
        String usr = txtUsr.getText().toString();
        String pass = txtPass.getText().toString();

        boolean result;
        result = LogicController.logInWebService(this, usr, pass);

        if(result){
            //doSomething in response to the result
            //need to execute this after logInWebService is done
        }
    }
}

Clase LogicController:

public class LogicController extends AppCompatActivity {
    private WebService myWebService;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        myWebService = new WebService(1);
    }

    public static boolean logInWebService(Context context, String usr, String pass){
        boolean result = WebService.logInWebService(context, usr, pass);
        return result;
    }
}

Clase WebService:

    public class WebService {
    private static boolean result;

    public WebService(int idGestor) {
        this.idGestor = idGestor;
    }

    public static boolean logInWebService(Context context, final String usr, final String pass) {
        String url = "https://webpage.myPhpWS.php?"+"idusr="+usr+"&pass="+pass;
        result = false

        JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {
                if(someOperation){
                    result = true;
                }
            }
        },
        new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                System.out.println("Error"+error.getMessage());
            }
        });

        RequestQueue request = Volley.newRequestQueue(context);
        request.add(jsonObjectRequest);

        return result; //this is the final result needed
    }
}
  • Utilizo clases anidadas ya que la clase WebService realiza varias solicitudes y debo poder manejarlas por separado. Preferiría, si es posible, no agregar clases a este esquema.
  • No pude encontrar un hilo que tocara este tema específico.
  • Cualquier ayuda sería útil, incluso si estoy teniendo un mal enfoque desde el principio.

Gracias de antemano.

-1
Gabriel Candia 21 feb. 2018 a las 20:04

2 respuestas

La mejor respuesta

Puede utilizar una interfaz de devolución de llamada y pasarla como parámetro a LogicController.logInWebService(this, usr, pass,callback);.

1- crear interfaz ResultCallback

interface ResultCallback {

void on success();
void onFailure();
   }

2- páselo al logInWebService

 //show progress dialog before making the request
 LogicController.logInWebService(this, usr, pass,new ResultCallback (){

                @Override
                public void onSuccess() {
                    //hide progress and show success message
                }

                @Override
                public void onFailure() {
                    //hide progress and show error
                }
            }
    );

3- luego modifica tu método logInWebService()

 public static boolean logInWebService(Context context, final String usr, final String pass,ResultCallback callback) {
    String url = "https://webpage.myPhpWS.php?"+"idusr="+usr+"&pass="+pass;
    result = false

    JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
        @Override
        public void onResponse(JSONObject response) {
        callback.onSuccess(); //you can pass sth to this method
            if(someOperation){
                result = true;
            }
        }
    },
    new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            System.out.println("Error"+error.getMessage());
             callback.onSuccess();
        }
    });

    RequestQueue request = Volley.newRequestQueue(context);
    request.add(jsonObjectRequest);

    return result; //remove this and return void instead.
}

Un mejor enfoque es utilizar los observables Rxjava.

1
Bishoy Abd 21 feb. 2018 a las 17:31

Ok, tuve el mismo problema, lo acabo de resolver con ObservableInteger, solo declaro

private ObservableInteger mObsInt;

Luego en onCreate configurar un oyente

 //Listener
        mObsInt = new ObservableInteger();
        mObsInt.set(0);

        mObsInt.setOnIntegerChangeListener(new OnIntegerChangeListener()
        {
            @Override
            public void onIntegerChanged(int newValue)
            {
                if (mObsInt.get()==1)
                    Log.e("Downloads"," mObsInt 1");
                Log.e("Download1"," Finished first process ");
                if (mObsInt.get()==2){
                    Log.e("Downloads"," mObsInt 2");
                    Log.e("Download2"," Finished second process ");
                    mProgressDialog.dismiss();
                    Intent mainIntent = new Intent().setClass(LoginActivity.this, Principal.class);
                    startActivity(mainIntent);
                    finish();
                }
            }
        });

Y luego haz esto (después de que un proceso haya finalizado)

mObsInt.set(mObsInt.get()+1);

Por lo que contará, si lo primero termina obsInt será 1, y cuando termine el segundo, obsInt será 2, así que después de obsInt == 2, puedes pasar a la otra actividad o proceso que necesites

Feliz codificación!

0
Gastón Saillén 21 feb. 2018 a las 17:19