2017-04-12 62 views
1

我正在编写一个程序,需要为服务器连接运行单独的线程,但我不知道如何正确使用AsyncTask。我已阅读文档,但仍不确定如何正确使用它。如何使用AsyncTask?

这是应该给我连接到服务器的方法:

public boolean start() 
{ 
    // try to connect to the server 
    try { 
     socket = new Socket(server, port); 
    } 
    // if it failed not much I can so 
    catch(Exception ec) { 
     display("Error connectiong to server:" + ec); 
     return false; 
    } 

    /* Creating both Data Stream */ 
    try 
    { 
     sInput = new ObjectInputStream(socket.getInputStream()); 
     sOutput = new ObjectOutputStream(socket.getOutputStream()); 
    } 
    catch (IOException eIO) { 
     display("Exception creating new Input/output Streams: " + eIO); 
     return false; 
    } 

    // creates the Thread to listen from the server 
    new ListenFromServer().start(); 
    // Send our username to the server this is the only message that we 
    // will send as a String. All other messages will be ChatMessage objects 
    try 
    { 
     sOutput.writeObject(username); 
    } 
    catch (IOException eIO) { 
     display("Exception doing login : " + eIO); 
     disconnect(); 
     return false; 
    } 
    // success we inform the caller that it worked 
    return true; 
} 

的ListenFromServer类以上使用:

class ListenFromServer extends Thread { 

    public void run() { 
     while(true) { 
      try { 
       String msg = (String) sInput.readObject(); 
       // if console mode print the message and add back the prompt 
       if(clientActivity == null) { 
        System.out.println(msg); 
        System.out.print("> "); 
       } 
       else { 
        clientActivity.append(msg); 
       } 
      } 
      catch(IOException e) { 
       if(clientActivity != null) 
        clientActivity.connectionFailed(); 
       display("Server has close the connection: " + e); 
       break; 
      } 
      // can't happen with a String object but need the catch anyhow 
      catch(ClassNotFoundException e2) { 
      } 
     } 
    } 
} 

我知道我应该使用AsyncTask,但我不知识。

回答

0

请参见下面的代码,

private class ListenFromServer extends AsyncTask<Void, Void, Void> { 

    @Override 
    protected Void doInBackground(Void... params) { 
     while(true) { 
     try { 
      String msg = (String) sInput.readObject(); 
      // if console mode print the message and add back the prompt 
      if(clientActivity == null) { 
       System.out.println(msg); 
       System.out.print("> "); 
      } 
      else { 
       clientActivity.append(msg); 
      } 
     } 
     catch(IOException e) { 
      if(clientActivity != null) 
       clientActivity.connectionFailed(); 
      display("Server has close the connection: " + e); 
      break; 
     } 
     // can't happen with a String object but need the catch anyhow 
     catch(ClassNotFoundException e2) { 
     } 
    } 

    } 

    @Override 
    protected void onPostExecute(Voidresult) { 
     //after completed 



    try 
    { 
     sOutput.writeObject(username); 
    } 
    catch (IOException eIO) { 
     display("Exception doing login : " + eIO); 
     disconnect(); 
     return false; 
    } 
    // success we inform the 
    } 

    @Override 
    protected void onPreExecute() {} 

    @Override 
    protected void onProgressUpdate(Void... values) {} 
} 

调用此Asyntask,

新ListenFromServer()EXCUTE()。

1

AsyncTask比看起来容易得多。有三种主要方法需要您担心开始。在AsyncTask上调用execute()将启动这些方法:

onPreExecute(); 

这在调用doInBackground()之前调用。如果需要的话,你可以在这里进行设置。也许设置ProgressBar的可见性或其他东西。

doInBackground() 

这是发生异步操作的地方。如果您需要进行网络通话或其他任何操作,请将代码放在此处。

onPostExecute(); 

当doInBackground()完成时调用它。无论从doInBackground()返回什么都会传递给此方法。请注意,此方法在主线程上运行,因此您可以从中更改UI。

现在的实际类本身:

public class MyTask extends AsyncTask<String, Integer, Boolean> { 

} 

你会发现,它有三个类型的参数。第一种类型(字符串)是在执行时将被发送到任务的参数的类型。例如,如果您需要在执行任务时向任务发送一个字符串,则会将它们传递给execute()方法。例如:

myTask.execute("these", "strings", "will", "be", "passed", "to", "the", "task"); 

注意,您可以使用“无效”这里(资本V),如果你不想从execute()方法的任何通过。

public class MyTask extends AsyncTask<Void, Integer, Boolean> { 

} 

现在,要了解如何访问这些字符串,我们需要转到任务中的doInBackground()方法。

@Override 
protected Boolean doInBackground(String... params) { 
    //... 
} 

你会注意到doInBackground()方法有一个可变参数。

String... params 

是您在前面通过execute()传入的字符串,打包到数组中。所以String“these”位于params [0],“will”位于params [2]。

第二种类型的参数,则

Integer 

是将被传递到onProgressUpdate()在调用从doInBackground publishProgress()()对象的类型。这用于在任务执行仍在进行时从主线程更新UI。我们现在不会担心这一点 - 您可以稍后解决。如果你不打算使用onProgressUpdate(),你也可以在这里传递'Void'。

现在的第三个和最后型放慢参数

Boolean 

这是对象doInBackground()将返回的类型。这是不言而喻的。你可以通过“太虚将该参数置,以及如果你想,只要注意,您仍然需要

return null; 

从doInBackground()。那么一旦doInBackground()完成,这个返回值会发生什么?它被发送到

@Override 
protected void onPostExecute(Boolean...aBoolean) { 

} 

从这里,你可以做任何你想要的结果,在这种情况下是一个布尔值。再次,这个方法在主线程上运行,所以你可以从这里更新视图。很多时候,我将一个监听器传递给AsyncTask并从onPostExecute()调用它。例如:

@Override 
protected void onPostExecute(Boolean aBoolean) { 
    mListener.onTaskFinished(aBoolean); 
} 

如果您的AsyncTask类的活动中直接声明,那么你可以只更新视图或做任何你需要直接从onPostExecute做()。最后还有一件事,你也可以用更传统的方式将对象传递给你的任务 - 通过构造函数。如果你不想传递参数,你不必传递()。

new MyTask("hello", 55).execute(); 

只需将它们设置到AsyncTask类中的正确字段并设置好即可。您可以像使用其他课程一样使用它们。

+0

有没有办法可以从AsyncTask返回一个变量?因为执行所有这些操作的方法需要返回一个布尔变量,所以许多其他方法和类都会询问'if(!start())return;' –

+0

您需要使用回调函数。这很容易,并在[这篇文章]顶部的答案(http://stackoverflow.com/questions/12575068/how-to-get-the-result-of-onpostexecute-to-main-activity-because-asynctask-is- a)会告诉你如何去做。 – jburn2712