调试时 onPostExecute() 与 doInBackground() 无关

onPostExecute() not related to doInBackground() while debugging

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

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

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

编辑:

我用 Progress Dialog 替换了 .get() 以阻止 UI,但现在我得到 Toast 甚至在 AsyncTask 之前我的表单无效工作。而且,即使从 doInBackground() 我得到 TRUE,第一次点击 signupValid 也是错误的,第二次点击 AsyncTask return 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;

如果我对问题的理解正确 - 存在竞争条件,使得 SignupActivitySignup 任务执行完成之前触发 toast。因此:

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

}