调试时与doInBackground()不相关的onPostExecute()

时间:2019-01-27 13:41:36

标签: java android android-asynctask android-room android-jetpack

我在onPostExecute()类中的AsyncTask方法有问题。

我有一个 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; }

这实现了我的界面来捕获onPostExecute()的结果:

public interface SignupListener{
    void onSignupPerformed(Boolean result);
}

现在,我在代码中触发的 AsyncTask

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);
}

我的问题是,为什么当我第一次单击按钮时,函数返回Boolean.TRUE但在SignupActivity signupValid中的变量是false(注册表单没有退出,而用户却是已添加到数据库中),但是当我第二次单击“注册”按钮时,ofc的注册失败(因为我们几秒钟前就创建了新用户),但是signupValid更改为true并通过了注册表单?我需要单击两次SignupButton才能最终退出表单。感谢您在我的代码中发现错误

编辑:

我用.get()替换了Progress Dialog来阻止UI,但是现在我什至在Toast进行注册之前就得到了AsyncTask无效的表单。而且,即使我从signupValid得到doInBackground(),第一次单击TRUE还是假的,第二次单击AsyncTask返回FALSE却是signupValid更改为true

我的 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);
}

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;

1 个答案:

答案 0 :(得分:1)

如果我正确理解了该问题,则有一种竞赛条件会导致SignupActivity在执行Signup任务之前先烤面包。因此:

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);
 }

应该是listener的一部分(现在看来这些行是在异步任务完成之前执行的)

为了澄清自己:

@Override
public void onSignupPerformed(Boolean result)
{ 
     if(result) {
        Toast.makeText(SUCCES);
        finish();
     } else {
        Toast.makeText(ERROR);
     }

}