0

Im looking solution for my problem.

I call an AsyncTask in my Activity:

login.execute(emailText.getText().toString(), passwordText.getText().toString());

In class Login i checking, if user exist.

public class Login extends AsyncTask<String, Boolean, Void> {

public Login(Application application){
    repository = new Repository(application);
}

@Override
protected Boolean doInBackground(String... body){
    try {
        user = repository.getUser(body[0], body[1]);
        if (user != null)
            return true; //wont work
        else {
            return false;
        }
    }
    catch(Exception e){
        return null;
    }
}

protected void onPostExecute(Long result) {
   //i want to have bool value here that i will see in my activity
}

My question is, how to get bool value from AsyncTask when condition in if match? If it is any possible way to call method like that?

boolean valid = login.execute();

Thanks for help

michasaucer
  • 4,562
  • 9
  • 40
  • 91
  • AsyncTask and you will be good to go . Also based on this the correct signature of this method will be void onPostExecute(Boolean result). – Rohit Singh Jan 24 '19 at 12:45

4 Answers4

1

Build your asyncTask like:

public class Login extends AsyncTask<Void, Void, Void> {

private boolean valid;

@Override
public Void doInBackground(Void... records) {
    // do work here
    user = repository.getUser(body[0], body[1]);
    if (user != null)
       valid = true;
    else
       valid = false;
    return null;
}

@Override
protected void onPostExecute(Void result) {
    callMyMethodWithTheUpdatedValue(valid);
}

}

Marco
  • 352
  • 2
  • 14
  • Could you explain me more, what callMyMethodWithTheUpdatedValue(valid)` do and how to invoke it? – michasaucer Jan 24 '19 at 12:36
  • onPostExecute is called from the main thread right after doInbackground, so you can invoke any other method defined in the Activity with the correct value; instead of returning the value from the AsyncTask. Take a look at this for more details: https://stackoverflow.com/a/15762539/5382017 – Marco Jan 24 '19 at 12:37
  • Thanks for your advice, but reference two whole object with one `boolean` its too many i think. There is no siple way to return that `bool` from `onPostExecute()`? – michasaucer Jan 24 '19 at 12:43
  • 1
    If you want to react after onPostExecute you can modify a little bit your code and implement an interface to do that: basically you instantiate a listener in your activity and call the method of that listener from your onPostExecute(). Again follow this link for more informations: https://stackoverflow.com/a/13815960/5382017 – Marco Jan 24 '19 at 12:46
1

Change your code like below code:

public class Login extends AsyncTask<String, Boolean, Boolean> {

public Login(Application application){
    repository = new Repository(application);
}

@Override
protected Boolean doInBackground(String... body){
    try {
        user = repository.getUser(body[0], body[1]);
        if (user != null)
            return Boolean.TRUE; //wont work
        else {
            return Boolean.FALSE;
        }
    }
    catch(Exception e){
        return Boolean.FALSE;
    }
}

protected void onPostExecute(Boolean result) {
   //i want to have bool value here that i will see in my activity
   Log.e("POST_EXECUTE", "" + result);
}
Asif Patel
  • 1,744
  • 1
  • 20
  • 27
1

Change the onPostExecute() argument type to Boolean and then tell who would be interested in the result what happened.

For this last part you can have an interface and have that someone (intereste class) implement it.

public class Login extends AsyncTask<String, Boolean, Boolean> {

  private LoginListener listener;

  public Login(Application application, LoginListener listener){
    repository = new Repository(application);
    this.listener = listener;
  }

  @Override
  protected Boolean doInBackground(String... body){
    try {
        user = repository.getUser(body[0], body[1]);
        if (user != null)
            return true; //wont work
        else {
            return false;
        }
    }
    catch(Exception e){
        return null;
    }
  }

  protected void onPostExecute(Boolean result) {
   listener.onLoginPerformed(result)
  }



  public static interface LoginListener{
    public void onLoginPerformed(Boolean result);
  }
}

Then suppose you want MainActivity to react upon the login:

public class MainActivity extends AppCompatActitvity implements LoginListener{
    ....
    // When you create the Login object, in onCreate() for example:
    // new Login(application, this); // this is the activity acting as listener...

    @Override public void onLoginPerformed(Boolean result){
        // do what you want to do with the result in Main Activity
    }

}
Juan
  • 5,525
  • 2
  • 15
  • 26
1

The idea of AsyncTask is not to "get" a result but make something happen in the background without blocking the UI. Your approach will block the UI thread and until the server returns a response the app will be blocked and if that state stays for more than 5 secs the user will see a ANR

But to answer your question: In oder to get boolean result from the AsyncTask you need to extend the correct class, in your case it is: AsyncTask<String, Void, Boolean>, because the AsyncTask types are the following:

The three types used by an asynchronous task are the following:

Params, the type of the parameters sent to the task upon execution.

Progress, the type of the progress units published during the background computation.

Result, the type of the result of the background computation.

So to answer your question, your code will be:

//USAGE
Login l = new Login();
Boolean valid = l.execute("user", "pass").get(); 
/* but the UI thread will be 
blocked, meaning the following code will not be executed until the variable 
valid is populated */ 

//AsyncTask
public class Login extends AsyncTask<String, Void, Boolean> {

public Login(Application application){
    repository = new Repository(application);
}

@Override
protected Boolean doInBackground(String... strings){
    try {
        user = repository.getUser(strings[0], strings[1]);
        if (user != null)
            return true; //wont work
        else {
            return false;
        }
    }
    catch(Exception e){
        return null;
    }
}

protected void onPostExecute(Boolean result) {
   // this method is no longer needed since you will get the result directly 
   // from the doInBackground method

}

Nor for a solution that will actually work: I suggest that every-time a user wants to log in the app should present a progressDialog window informing the user that it has to do a time consuming task, and after the process is completed inform the user of the status. In order to do this use the following code:

//USAGE
   @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test);
        Login l = new Login();
        l.execute("user", "pass"); 
        /* but the UI thread will be 
        blocked, meaning the following code will not be executed until the                             
        variable valid is populated */
    }

public void userLoggedIn() {
    // do something when a user loggs in sucessfully
}

public void wrongCredentials() {
    // alert the user that he didn't put in the correct credentials
}

//AsyncTask
public class Login extends AsyncTask<String, Void, Boolean> {


    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        // show a dialog window here when the AsyncTask starts
    }

    @Override
    protected Boolean doInBackground(String... strings){
        try {
            user = repository.getUser(strings[0], strings[1]);
            if (user != null)
                return true; //wont work
            else {
                return false;
            }
        }
        catch(Exception e){
            return null;
        }
    }

       @Override
    protected void onPostExecute(Boolean aBoolean) {
        super.onPostExecute(aBoolean);
        // dismiss the dialog window here after the AsyncTask finishes
        if (aBoolean) {
            userLoggedIn();
        } else {
            wrongCredentials();
        }
    }
}
Ruzin
  • 1,645
  • 2
  • 14
  • 14
  • Thanks for nice replay! But i want to store `Login` `AsyncTask` class in diffrent java file. Is it possible to show something like process dialog in that `login` class? – michasaucer Jan 24 '19 at 13:36
  • "process dialog"? Do you mean "progress dialog"? – Ruzin Jan 24 '19 at 13:49
  • Yes, progress dialog – michasaucer Jan 24 '19 at 13:51
  • 1
    You can show the progress dialog (but since it's deprecated I suggest using some alternative - I just call it that for easy understanding) even if the AsyncTask is in a separate file. Just pass a context from the activity you are calling the AsyncTask from in the AsynkTask's constructor and use that context for the "Progress Dialog" – Ruzin Jan 24 '19 at 13:54