代码之家  ›  专栏  ›  技术社区  ›  michasaucer

将AsyncTask重置为多次执行

  •  0
  • michasaucer  · 技术社区  · 7 年前

    有什么方法可以用吗 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){ }
    }
    

    我读到了,我们可以重置 异步任务 通过制造新的 异步任务 ( Task = new Login() ) StackOverflow Thread 但它对我不起作用。当我试图在我的 Login 班级:

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

    我的Android应用程序崩溃。我的问题是,重置的最佳方法是什么 异步任务 在不同的文件中实现,然后我的 Activity 班级?或者也许有更好的方法 登录 比实现整个登录逻辑的活动 异步任务 ?

    编辑:

    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 回复  |  直到 7 年前
        1
  •  1
  •   John Bollinger    7 年前

    你说,

    我打电话 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 实例只能执行一次,这将在第二次单击“登录”按钮时失败(如果不是很快,由于其他原因)。

    你也说,

    我读到了,我们可以通过创建新的 异步任务 ( Task = new Login() )

    但是 不 ,不会重置任何内容,而且确实 异步任务 无法重置对象。你读到的建议是 代替 使用过的 异步任务 有了新的实例。实例化新的 异步任务 对其他人没有特别的影响。如果您希望采用这种方法,那么它可能看起来像这样:

    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 非 final ,所以可能是包含类的实例变量,而不是从中摘录代码的方法的局部变量。

    然而 你最好的前进方式可能是放弃 异步任务 总而言之。当您这样使用它时:

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

    …你挫败了整个目标。您正在创建一个线程,在该线程中运行块,直到任务完成(这就是 AsyncTask::get 是 对于 ,因此任务是有效同步的。如果这是你所需要的,那么你应该更直接地完成你想要的工作,而不是把它包装在 异步任务 .

    推荐文章