onPostExecute (), не связанный с doInBackground () при отладке - PullRequest
0 голосов
/ 27 января 2019

У меня проблема с моим 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);
}

Мой вопрос: почему, когдая сначала нажимаю на кнопку, func return Boolean.TRUE, но в SignupActivity signupValid переменная равна false (форма регистрации не завершается, но пользователь добавляется в БД), но когда я нажимаю кнопку регистрации во второй раз, регистрация ofc не удалась(потому что мы создали нового пользователя несколько секунд назад), но signupValid изменилось на true и Форма регистрации прошла?Мне нужно нажать SignupButton два раза, чтобы, наконец, выйти из формы.Спасибо за нахождение ошибки в моем коде

РЕДАКТИРОВАТЬ:

Я заменил .get() на Progress Dialog, чтобы заблокировать пользовательский интерфейс, но теперь я получаю Toast с недействительнымФорма еще до AsyncTask для регистрации сделай свою работу.И все же, при первом нажатии signupValid ложно, даже если с doInBackground() я получаю TRUE, при втором нажатии AsyncTask возврат FALSE, но signupValid изменяется на 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);
}

И База данных приложений:

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 голосов
/ 27 января 2019

Если я правильно понял проблему - есть условие гонки, которое заставляет 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);
     }

}
...