概述
Android并不允许开发人员在UI主线程中直接向服务器发起请求,因为如果请求得不到响应,那么UI线程就可能会被挂起,你的老板就会指着你的鼻子大吼“你特么这编的什么软件!”。
所以我们需要借助AsyncTask类来产生一个异步线程,然后在这个异步线程中向服务器发起异步请求。
一、编写异步处理类,继承AsyncTask
public class MyTask extends AsyncTask<String,Void,String>{
//...
}
注意,在继承AsyncTask的时候,后面有一组泛型参数组,内有三个参数,这三个参数的含义如下:
AsyncTask<Params, Progress, Result>
Params: 这个泛型指定的是我们传递给异步任务执行时的参数的类型
Progress: 这个泛型指定的是我们的异步任务在执行的时候将执行的进度返回给UI线程的参数的类型
Result: 这个泛型指定的异步任务执行完后返回给UI线程的结果的类型
如果你不想指定这三个泛型的话,也可以全部设定为Void。
在继承自类后,需要重载以下几个方法:
doInBackground():该方法会在主线程执行时,异步执行你希望做的事情。在本例中,它发起了http请求。
onPostExecute():该方法会在doInBackground执行结束后,由主线程自动调用。在本例中,它处理了请求结果。
onPreExecute():该方法会在异步程序被执行前,由主线程自动调用。
onCanncelled():该方法会在用户取消线程操作时使用。在主线程中调用onCanncelled即可。
二、重载doInBackground方法
继承了AsyncTask类之后,我们必须要实现doInBackground方法,在这个方法里面来执行我们希望异步线程处理的事情:
@Override
protected String doInBackground(String... params) {
//...
}
在这里,我们需要注意两个地方:
1、doInBackground方法的入参,这个入参是一个不定长数组,该数组的类型取决与我们的类在继承AsyncTask的时候,在泛型参数列表中的第一个参数的类型,也即下方标示为红色加粗的那个:
AsyncTask<
Params, Progress, Result>
2、doInBackground方法的返回类型,该类型取决于我们的类在继承AsycnTask的时候,在泛型参数列表中的第三个参数的类型,也即下方标示为红色加粗的那个:
AsyncTask<Params, Progress,
Result>
该返回类型同时也是重载方法onPostExecute()的入参类型。
三、向服务器发起请求
在doInBackground方法的内部,我们就可以向服务器发起请求了:
@Override
protected String doInBackground(String... params) {
String responseXml = "";//返回的值
try {
String requestXml = params[0];//从入参中获得请求参数
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(this.getWebserviceUrl());
ByteArrayEntity byteArrayEntity = new ByteArrayEntity(requestXml.getBytes("UTF-8"));
post.setEntity(byteArrayEntity);
post.setHeader("Accept-Charset", "UTF-8");
//获取response响应
HttpResponse httpResponse = client.execute(post);
HttpEntity httpEntity = httpResponse.getEntity();
byte[] responseContent = EntityUtils.toByteArray(httpEntity);
responseXml = new String(responseContent,"UTF-8");
} catch (Exception e) {
e.printStackTrace();
responseXml = "出现了错误!";
}
return responseXml;
}
发送请求部分的代码就是非常常见的基于HttpClient来发送请求的过程,这里就不多赘述了。
在doInBackground方法的最后,我们获得到了来自服务器的响应数据,并且return了出来,那么接下来就是来处理响应数据了。
三、重载onPostExecute方法
/**
* 在doInBackground 执行完成后,onPostExecute 方法将被UI主线程自动调用,我们可以用它来处理服务器响应数据
*/
@Override
protected void onPostExecute(String result) {
//入参的“String result”就是重载方法“doInBackground()”的返回值,在本例中,它代表服务器端返回的响应数据
}
四、重载其它方法
在本例中,其它方法并没有发挥至关重要的作用,我们仅作简单说明:
/**
* 在用户取消线程操作的时候调用。在主线程中调用onCancelled()的时候调用。
*/
@Override
protected void onCancelled() {
// TODO Auto-generated method stub
super.onCancelled();
}
/**
* 该方法将在执行实际的后台操作前被UI 线程调用
*/
@Override
protected void onPreExecute() {
// TODO Auto-generated method stub
}
/**
* UI主线程将调用这个方法在界面上展示任务的进展情况,例如通过一个进度条进行展示。
*/
@Override
protected void onProgressUpdate(Void... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
}
五、在主线程发起请求
经过了上面4个步骤,我们就完成了一个能够通过异步线程向服务器发送请求的类,接下来,就是在主线程中调用这个类,并实例化了:
MyTask myTask = new MyTask();
myTask.execute("在这里输入需要发送到服务器的请求参数");