调试时 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;
如果我对问题的理解正确 - 存在竞争条件,使得 SignupActivity
在 Signup
任务执行完成之前触发 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);
}
}
我在 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;
如果我对问题的理解正确 - 存在竞争条件,使得 SignupActivity
在 Signup
任务执行完成之前触发 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);
}
}