Android重新启动AsyncTask



尝试重新打开活动后,重新启动AsyncTask时遇到一些问题。

当我第一次打开活动时,我调用它来启动第一次工作的AsyncTask

myTask connectedTask;
connectedTask = new myTask();
connectedTask.execute();
public class myTask extends AsyncTask<Integer,Integer, Integer> {
    @Override
    protected Integer doInBackground(Integer... arg0) {
        //Increase timer and wait here in a loop
        System.out.println("ASYNC TASK STARTING!");
        return IsSocketConnected();
    }
    protected void onPostExecute(Integer result) {
        //Something you want to do when done?
        System.out.println("ASYNC TASK DONE!");
        // if it was connected successfully 
        if(result == 1) {
            // remove the progress bar
            proBar.setVisibility(View.GONE);
            // Discover available devices settings and create buttons
            CreateButtons(btnList);
        }
    }
}
IsSocketConnected(); // checks for a bluetooth connections to be done. 

当我回到上一个活动并尝试再次启动该活动时,我无法再次启动AsyncTask

我读到,只要我创建了一个AsyncTask的新实例,我就应该重新启动这些任务。

还有什么我应该做的吗?

谢谢你,

OP找到了解决方案,这很好,但对未来的读者来说是有帮助的;

你可以添加一个方法,比如:

public class MainActivity extends Activity {
    
     public static MyTask loadTextDataTask;
     
     //... methods
     public class MyTask extends AsyncTask<Void, Void, Void> {
         //... methods
         public void selfRestart() {
             loadTextDataTask = new MyTask();
         }
     }

}

然后你可以从任何其他类使用它,比如:

MainActivity.loadTextDataTask.selfrestart();

注意没有真正的方法来重新启动现有的instnace,即使我们调用AsyncTask.cancel(true),对AsyncTask.execute()的第二次调用也会抛出

IllegalStateException: Cannot execute task: the task has already been executed

这是正确的,您只需创建一个新实例并执行它即可重新启动。我想知道你是从什么功能开始执行任务的?在onResume()函数中启动它可能是个好主意,以防活动在返回前台之前没有被破坏。

感谢您的评论,他们帮了你很多忙。我决定取消AsyncTask。最后,我使用了一个普通的可运行线程,并使用Handlers将消息发布回UI线程。这是代码:

        // Start thread here only for IsSocketConnected
        new Thread(new Runnable() {
            public void run() {
                //Add your code here..
                IsSocketConnected();
            }
        }).start();

// handler that deals with updating UI
public Handler myUIHandler = new Handler()
{
    @Override
    public void handleMessage(Message msg)
    {
        if (msg.what == Bluetooth.STATE_CONNECTED)
        {
            //Update UI here...
            Log.d(TAG, "Connected");


            // Discover available devices settings and create buttons
            CreateButtons(btnList);
        } else if(msg.what == Bluetooth.STATE_NONE) {
            Log.d(TAG, "NOT Connected");
        }

}

// in the IsSocketConnected() I call this 
Message theMessage = myUIHandler.obtainMessage(Bluetooth.STATE_CONNECTED);
myUIHandler.sendMessage(theMessage);//Sends the message to the UI handler.

到目前为止,这是有效的。再次感谢。希望这能帮助

尝试将此代码放入onResume()中,如:

@Override
public void onResume()
{
    super.onResume();
    myTask connectedTask = new myTask();
    connectedTask.execute();
}

当您恢复到Activity时,它应该会创建一个新对象。您没有发布它,但可能是在onCreate()中创建对象,该对象只运行一次。

我对处理Socket连接的建议是只对Thread本身进行子类化。

更好的是,使用OnPostExecute来触发任务的新实例。如果任务完成,它将启动。但是使用布尔值来防止它每次都触发自己

protected void onPostExecute(Void result) {
if(someboolean==true) { 
                            new instance of task;
                            instance.execute;
                someboolean=false;
                }
}

开发者网站说

当首次引入时,AsyncTasks是在单个后台线程上串行执行的。从DONUT开始,它被更改为允许多个任务并行操作的线程池。从HONEYCOMB开始,任务在单个线程上执行,以避免由并行执行引起的常见应用程序错误。

如果您确实想要并行执行,可以使用THREAD_POOL_Executor调用executeOnExecutor(java.util.courrent.Executor,Object[])。

从HONEYCOMB开始,AsyncTask默认使用一个Executor来执行任务,然后一次运行一个任务。这意味着,如果在对任何活动(主线程上的任何位置)调用myTask.execute()之后调用它,则第二个调用将等待调用doInBackground方法,直到第一个任务完成。如果您的IsSocketConnected()方法没有立即返回,它将在主线程上的任何位置再次调用AsyncTask.execute()方法后阻止任何doInBackground()调用,直到当前Task完成。

如果您的isSocketConnected()使用了任何阻塞操作,如wait()或Thread.sleep(),您可以通过在活动的onDestroy()回调中调用myTask.cancel(true)来解决它,这将引发InterruptedException。只需确保在将导致线程退出doInBackground方法的位置捕获InterruptedException。

您还可以通过使用自定义的ThreadPoolExecutor并调用AsyncTask.executeOnExecutor(Executor)方法来解决问题。

不使用:connectedTask=新建myTask();connectedTask.execute();

简单使用:newconnectTask.execute();在你想要重新启动任务的地方使用它!!

最新更新