Issue
I have a problem with my onPostExecute()
method in AsyncTask
class.
I have an SignupActivity
:
public class SignupActivity extends AppCompatActivity implements SignupListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.signup_activity);
//new task, i pass context and interface to it
signup = new Signup(getApplicationContext(), this);
signupButon.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
if(validate()) {
try {
//new task every click
Signup newSignup = new Signup(signup);
//here start AsyncTask
newSignup.execute(name, email, password).get();
} catch (Exception e) {
Toast.makeText(ERROR);
}
// if sign up succes, == true;
if(signupValid) {
Toast.makeText(SUCCES);
finish();
} else {
Toast.makeText(ERROR);
}
}
}
});
}
// my own interface for getting result as bool from onPostExecute
@Override
public void onSignupPerformed(Boolean result){ this.signupValid = result; }
That implements my interface to catching result from onPostExecute()
:
public interface SignupListener{
void onSignupPerformed(Boolean result);
}
Now, AsyncTask
that i trigger in code:
public class Signup extends AsyncTask<String, Boolean, Boolean> {
public Signup(Context context, SignupListener listener){
db = ApplicationDatabase.getDatabase(context);
this.context = context;
this.listener = listener;
}
public Signup(Signup signup){
//constructor to make new task based on first task
db = signup.db;
context = signup.context;
listener = signup.listener;
}
protected Boolean doInBackground(String... body){
try {
user = db.userDao().getUser(body[0], body[1], body[2]);
if (user == null) {
// user is null, so we can add new one to DB
db.userDao().insertUser(new User(body[0], body[1], body[2]));
return Boolean.TRUE; //signup go good, return true
} else {
return Boolean.FALSE; //signup go bad, return false
}
} catch(Exception e) { }
return null;
}
protected void onPostExecute(Boolean result) {
//catching result from doInBackground
listener.onSignupPerformed(result);
}
My question is, why when i first click on button, func return Boolean.TRUE
but in SignupActivity
signupValid
variable is false
(signup form not exit, but user is added to DB), but when i click signup button second time, ofc signup fail (because we make new user seconds ago) but signupValid
change to true
and Signup Form pass? I need to click SignupButton
two times to finally exit form. Thanks for finding error in my code
EDIT:
I replaced .get()
with Progress Dialog
to block UI, but now i get Toast
with not valid form even before AsyncTask
for Signup do his job. And still, in first click signupValid
is false even when from doInBackground()
i get TRUE
, on second click AsyncTask
return FALSE
but signupValid
is changed to true
My UserDAO:
@Dao
public interface UserDao {
@Query("SELECT * FROM users WHERE email = :email AND password = :password AND username = :username")
User getUser(String username, String email, String password);
}
And ApplicationDatabase:
public abstract class ApplicationDatabase extends RoomDatabase {
public abstract UserDao userDao();
public static ApplicationDatabase getDatabase(final Context context){
if(INSTANCE == null){
synchronized (ApplicationDatabase.class){
if(INSTANCE == null){
INSTANCE = Room.databaseBuilder(context.getApplicationContext(), ApplicationDatabase.class, "database").build();
}
}
}
return INSTANCE;
}
private static volatile ApplicationDatabase INSTANCE;
Solution
If I understood the problem correctly - there is a race condition that makes the SignupActivity
to fire the toast before the execution of Signup
task is completed. Therefore:
signupButon.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
if(validate()) {
try {
//new task every click
Signup newSignup = new Signup(signup);
//here start AsyncTask
newSignup.execute(name, email, password).get();
} catch (Exception e) {
Toast.makeText(ERROR);
}
}
}
});
While these lines:
// if sign up succes, == true;
if(signupValid) {
Toast.makeText(SUCCES);
finish();
} else {
Toast.makeText(ERROR);
}
Should be a part of the listener
(right now it seems that these lines are executed BEFORE the completion of your async task)
To clarify myself:
@Override
public void onSignupPerformed(Boolean result)
{
if(result) {
Toast.makeText(SUCCES);
finish();
} else {
Toast.makeText(ERROR);
}
}
Answered By - ymz
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.