有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

我在AsyncTask类中的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返回Boolean.TRUE,但在SignupActivity{}中,变量是false(注册表单不退出,但用户被添加到数据库),但当我第二次单击注册按钮时,ofc注册失败(因为我们在几秒钟前创建了新用户),但signupValid更改为true,注册表单通过?我需要点击SignupButton两次才能最终退出表单。感谢您在我的代码中发现错误

编辑:

我用Progress Dialog替换了.get()以阻止UI,但现在我甚至在AsyncTask注册之前就用无效形式得到了Toast。尽管如此,在第一次单击中signupValid是假的,即使从doInBackground()我得到TRUE,在第二次单击中AsyncTask返回FALSE,但是signupValid更改为true

我的用户道:

@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) 个答案

  1. # 1 楼答案

    如果我正确理解了这个问题,那么有一个竞争条件使得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);
         }
    
    }