Сброс AsyncTask для многократного выполнения - PullRequest
0 голосов
/ 24 января 2019

Есть ли способ использовать AsyncTask.execute() несколько раз?

Я использую AsyncTask, чтобы проверить, существует ли User в моей базе данных комнат.

Мой Login.class выглядит так:

public class Login extends AsyncTask<String, Boolean, Boolean> {

public Login(Context context, LoginListener listener){
    db = ApplicationDatabase.getDatabase(context); //i get Room here
    this.context = context; //context of app
    this.listener = listener; //my interfece for observe Boolean, works ok
}

@Override
protected Boolean doInBackground(String... body){
    try {
        user = db.userDao().getUser(body[0], body[1]);
        if (user != null)
            return Boolean.TRUE; //we find user with credentials
        else {
            return Boolean.FALSE; //we not find user with that credentials (from body)
        }
    }
    catch(Exception e){
        return null;
    }
}

protected void onPostExecute(Boolean result) {
    listener.onLoginPerformed(result); //Boolen to activity
    selfRestart(); //i want to restart task here
}

private void selfRestart(){
    //maybe something to do here? its my own method
}

private ApplicationDatabase db;
private User user;
private LoginListener listener;
private Context context;

Я называю задачу следующим образом (мой Activity.class):

login = new Login(getApplicationContext(), this); 
//this is an interface that i implements in Activity definition

loginButton.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View v){
            //execute() here, i cuted some not necesery code from here
            try {
                // im using get because i want to get valu from AsyncTask
                login.execute(email, password).get();
            }
            catch(Exception e){ }
}

Я прочитал, что мы можем сбросить AsyncTask, сделав новый AsyncTask (Task = new Login()) StackOverflow Thread , но он не работает для меня. Когда я пытаюсь сделать что-то подобное в моем Login классе:

private void selfRestart(){
    Login task = new Login(context, listener);
    task.execute("");
    //im calling it in onPostExecute()
}

У меня вылетает приложение для Android. Мой вопрос: каков наилучший способ сброса AsyncTask, который реализован в файле diffrent, чем мой класс Activity? Или, может быть, есть лучший способ сделать Login активность, чем реализованная логика для входа в AsyncTask?

EDIT:

Logcat:

2019-01-24 15:45:31.407 1048-1048/com.example.admin.keystroke_dynamics E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.admin.keystroke_dynamics, PID: 1048
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.Boolean.booleanValue()' on a null object reference
    at com.example.admin.keystroke_dynamics.Activities.LoginActivity.onLoginPerformed(LoginActivity.java:62)
    at com.example.admin.keystroke_dynamics.Login.onPostExecute(Login.java:38)
    at com.example.admin.keystroke_dynamics.Login.onPostExecute(Login.java:14)
    at android.os.AsyncTask.finish(AsyncTask.java:692)
    at android.os.AsyncTask.-wrap1(AsyncTask.java)
    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:709)
    at android.os.Handler.dispatchMessage(Handler.java:105)
    at android.os.Looper.loop(Looper.java:156)
    at android.app.ActivityThread.main(ActivityThread.java:6523)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:942)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:832)

1 Ответ

0 голосов
/ 24 января 2019

Вы говорите,

Я звоню Task таким образом (мой Activity.class):

login = new Login(getApplicationContext(), this); 
//this is an interface that i implements in Activity definition

loginButton.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View v){
            //execute() here, i cuted some not necesery code from here
            try {
                // im using get because i want to get valu from AsyncTask
                login.execute(email, password).get();
            }
            catch(Exception e){ }
}

, но нет, вы не «вызывая» вашу задачу таким образом.Вы создаете один экземпляр задачи и настраиваете обработчик событий, который выполняет эту задачу - этот конкретный экземпляр - всякий раз, когда нажимается loginButton.Поскольку каждый экземпляр AsyncTask может быть выполнен только один раз, произойдет сбой при повторном нажатии кнопки входа (если не раньше, по какой-либо другой причине).

Вы также говорите,

Я прочитал, что мы можем сбросить AsyncTask, сделав новый AsyncTask (Task = new Login())

, но нет , который ничего не сбрасывает, да и вообще AsyncTask объекты не могут быть сброшены.Совет, который вы прочитали, состоял в том, чтобы заменить использованный AsyncTask новым экземпляром.Создание нового AsyncTask не оказывает особого влияния на других.Если вы хотите использовать этот подход, то он может выглядеть примерно так:

loginButton.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View v){
            Login myLoginTask = login; // keep a reference to the current task
            login = new Login(... arguments ...); // create a new task for the next click

            try {
                // use the original task
                myLoginTask.execute(email, password).get();
            }
            catch(Exception e){ }
}

Для этой конкретной реализации login должно быть не-1035 *, поэтому, вероятно, переменная экземпляра содержащего класса, а нелокальная переменная метода, из которого был извлечен ваш код.

HOWEVER , ваш лучший путь вперед может состоять в том, чтобы вообще отказаться от AsyncTask.Когда вы используете это так:

                login.execute(email, password).get();

... вы побеждаете всю цель.Вы создаете поток, в котором выполняется блок до тех пор, пока задача не будет завершена (это то, что AsyncTask::get равно для ), так что задача фактически синхронна.Если это то, что вам нужно, тогда вам нужно просто выполнить требуемую работу более напрямую, а не оборачивать ее в AsyncTask.

...