gpt4 book ai didi

android - 如何使用AsyncTask?

转载 作者:行者123 更新时间:2023-11-30 00:36:17 25 4
gpt4 key购买 nike

我正在编写程序,需要为服务器连接运行单独的线程,但是我不知道如何正确使用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,但是我不知道如何使用。

最佳答案

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

onPreExecute(); 


在调用doInBackground()之前调用它。如果需要,您可以在这里进行设置。也许设置ProgressBar的可见性或其他内容。

doInBackground()


这是异步操作发生的地方。如果您需要拨打网络电话或其他任何内容,请在此处输入代码。

onPostExecute();


doInBackground()完成时将调用此方法。从doInBackground()返回的所有内容都将传递给此方法。重要的是要注意,此方法在主线程上运行,因此您可以从中更改UI。

现在,对于实际的类本身:

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

}


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

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


请注意,如果您不想在execute()方法中传递任何内容,则可以在此处使用“无效”(大写V)。 (为清楚起见,您可以为这些参数传入任何类型的任何对象-Integer,Boolean,CustomClass等。请记住,如果您使用的是原始类型,则需要使用其包装器类,例如Integer ,布尔值。)

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

}


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

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


您会注意到doInBackground()方法具有vararg参数。

String... params 


是您之前通过execute()传入的字符串,打包成一个数组。因此,字符串“ these”位于params [0],而“ will”位于params [2]。

第二类参数

Integer


是从doInBackground()调用publishProgress()时将传递给onProgressUpdate()的对象的类型。用于在任务执行仍在进行时从主线程更新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);
}


如果直接在Activity中声明了AsyncTask类,则可以只更新Views或直接从onPostExecute()执行任何需要做的事情。

最后一件事,您还可以通过构造函数以更传统的方式将对象传递给Task。如果不想,则不必将参数传递给execute()。

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


只需将它们设置为AsyncTask类中的正确字段即可。您可以像使用其他任何类一样使用它们。

编辑:有一段时间,所以我想我会展示AsyncTask的完整实现,包括用于为结果创建回调的接口。

假设我需要对某个API进行网络调用,该API将返回JSON数据字符串(或任何类型的数据,重要的是它是字符串)。我的AsyncTask将需要一个URL来提供给我正在使用的任何网络客户端,因此我们将通过 execute()方法将其传递给它。因此,AsyncTask的第一个类型参数将是 String。由于我只打一个网络电话并得到一个响应,所以我不需要更新任何进度,因此第二个类型参数为 Void。我从API调用获得的响应是​​一个字符串,因此我将要从 doInBackground()方法返回该字符串。因此,第三个也是最后一个类型参数是 String

因此,我的AsyncTask类将如下所示:

public class NetworkTask extends AsyncTask<String, Void, String> {

//I'll use this to pass the result from onPostExecute() to the
//activity that implements the NetworkTaskListener interface, as
//well as notify that activity that onPreExecute has been called.
private NetworkTaskListener mListener;

//Set the NetworkTaskListener
public NetworkTask(NetworkTaskListener listener) {
mListener = listener;
}

//onProgressUpdate() doesn't need to be overridden

//Called after execute(), but before doInBackground()
@Override
protected void onPreExecute() {
mListener.onBeforeExecution();
}

//Called automatically after onPreExecute(). Runs in background.
@Override
protected void doInBackground(String... params) {
//"params" holds the Strings that I will pass in when I call
//execute() on this task. Since I'm only passing in one thing
//(a String URL), "params" will be an array with a length of one
//and the the String URL will be at params[0].

String url = params[0];
//Make the network call using whatever client you like.
//I'll use OkHttp just as an example.

OKHttpClient client = new OKHttpClient();
Request request = new Request.Builder()
.url(url)
.build();
Call call = client.newCall(request);

//It's okay to use a blocking network call here since we're
//already off of the main thread.
try {
Response response = call.execute();
//response.body().string() is the JSON data we want
String jsonData = response.body().string();
//This will be sent to onPostExecute()
return jsonData;
} catch (IOException e) {
e.printStackTrace();
Log.e("NetworkTask", "Error during network call");
//If there was an error, return null
return null;
}
}

//Called automatically after doInBackground(). The return value
//from doInBackground() is passed in here automatically.
@Override
protected void onPostExecute(String aString) {
//Check if the String is null to determine if there was an error
//while making the network call.
if (aString == null) {
mListener.onNetworkCallError();
return;
}
/*
If this is executed, it means that the response was successful.
Call the listner's onNetworkResponse() method and pass in the
string. The String will be used by the Activity that implements
the NetworkTaskListener.
*/
mListener.onNetowrkResponse(aString);
}

}


现在,我们已经设置了AsyncTask,现在我们需要创建NetworkTaskListener接口。它将包含3个方法(您已经在NetworkTask类中看到了),任何实现该接口的类都必须实现这些方法。在这种情况下,活动将实现此接口,因此必须覆盖所有3个方法。

public interface NetworkTaskListener {
//We call this method in onPreExecute() of the NetworkTask
void onBeforeExecution();

//Called from onPostExecute() when there was an error during the
//network call
void onNetworkCallError();

//Called from onPostExecute() when the response was successful
void onNetworkResponse(String jsonData);
}


现在已经处理了接口,我们只需要让我们的Activity来实现它即可。为简单起见,我将在Activity启动后立即启动NetworkTask。您会注意到,我们将 this传递给NetworkTask。这意味着我们要将Activity作为NetworkTaskListener传递给NetworkTask。记住,活动也是实现它的一个NetworkTaskListener。因此,当我们从NetworkTask调用 mListener.onNetworkResponse(jsonData)时,它是在Activity中调用“ onNetworkResponse(String jsonData)”方法。 (我知道,我知道...现在我正在解释基本的Java,但是我希望这一点很清楚,因为AsyncTasks经常被初学者使用。)

public class MainActivity extends Activity implements NetworkTaskListener {
//ProgressBar that will be displayed when NetworkTask begins
private ProgressBar mProgressBar;

//TextView that will be used to display the String that we get back
//from the NetworkTask
private TextView mTextView;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate();
setContentView(R.layout.activity_main);

mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
mTextView = (TextView) findViewById(R.id.textView);

String url = "https://www.exampleAPIurl.com";
//The listener that we are passing in here is this Activity
NetworkTask task = new NetworkTask(this);
//We pass the URL through the execute() method
task.execute(url);

/*
From this point, the NetworkTask will begin calling the
NetworkTaskListener methods, which are implemented below.
Specifically, it will call onBeginExecution(), and then either
onNetworkResponse(String jsonData) or onNetworkCallError();
*/
}

///////Implemented methods from NetworkTaskListener

@Override
public void onBeginExecution() {
//Called when the task runs onPreExecute()
mProgressBar.setVisibility(View.VISIBLE);
}

@Override
public void onNetworkCallError() {
//Called from task's onPostExecute() when a Network error
//occured
mProgressBar.setVisibility(View.INVISIBLE);
mTextView.setText("An error occured during the network call");
}

@Override
public void onNetworkResponse(String jsonData) {
//Called from task's onPostExecute() when network call was
//successful
mProgressBar.setVisibility(View.INVISIBLE);
mTextView.setText(jsonData);
}
}


请注意,您还可以将NetworkResponseListener用作匿名类,并且Activity不必实现它。

关于android - 如何使用AsyncTask?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43359374/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com