做过android开发的朋友们都知道,Android UI线程(或者叫主线程)是不安全的,如果想要在子线程里进行UI操作,就需要借助android的异步消息处理机制。最近学习了AsyncTask类,感觉很好用,特此学习总结。
AsyncTask是一个抽象类,所以我们在使用的时候需要创建一个子类继承它。继承时我们需要为AsyncTask类指定3个泛型参数。如下所示:
public class xx extends AsyncTask<Params, Progress, Result> { }
Params, Progress, Result,3个参数的用途如下:
1.Params
在执行AsyncTask 时需要传入的参数,可用于在后台任务中使用。
2.Progress
后台任务执行时,如果需要在界面上显示当前的进度,则使用这里指定的泛型作为进度单位。
3.当任务执行完毕后,如果需要对结果进行返回,则使用这里指定的泛型作为返回值类型。
如下是我在写一个有关android平台调用webservice时用到的
public class getRemoteInfoTask extends AsyncTask<Void,Integer, String> { @Override protected String doInBackground(Void... arg0) { // TODO 自动生成的方法存根 return getRemoteInfo(QueryNumber); } @Override protected void onPostExecute(String result) { text_result.setText(result); super.onPostExecute(result); } }
我们可以看到,第一个参数即Params被指定为Void,表示不需要传入参数;第二个参数即Progress被指定为Integer,表示使用整型数据来作为进度显示单位;第三个参数被指定为String,表示使用String数据来反馈执行结果。
在以上例子中,我重写了2个函数,也是最基本最常用的2个函数,除此之外,经常需要重写的函数有如下四个:
1. onPreExecute()
这个方法会在后台任务开始执行之间调用,用于进行一些界面上的初始化操作,比如显示一个进度条对话框等。
2. doInBackground(Params...)
这个方法中的所有代码都会在子线程中运行,我们应该在这里去处理所有的耗时任务。任务一旦完成就可以通过return 语句来将任务的执行结果进行返。在这个方法中是不可以进行UI 操作的,如果需要更新UI 元素,比如说反馈当前任务的执行进度,可以调用publishProgress(Progress...)方法来完成。
3. onProgressUpdate(Progress...)
当在后台任务中调用了publishProgress(Progress...)方法后,这个方法就很快会被调用,方法中携带的参数就是在后台任务中传递过来的。在这个方法中可以对UI 进行操作,利用参数中的数值就可以对界面元素进行相应的更新。
4. onPostExecute(Result)
当后台任务执行完毕并通过return 语句进行返回时,这个方法就很快会被调用。返回的数据会作为参数传递到此方法中,可以利用返回的数据来进行一些UI 操作,比如说提醒任务执行的结果,以及关闭掉进度条对话框等。
调用执行
new getRemoteInfoTask().execute();
以下是通过webservice获取号码归属地的例子,其中就用到了AsyncTask类
1 package com.example.webservice; 2 3 import java.io.IOException; 4 5 import org.apache.http.HttpServerConnection; 6 import org.ksoap2.SoapEnvelope; 7 import org.ksoap2.serialization.SoapObject; 8 import org.ksoap2.serialization.SoapSerializationEnvelope; 9 import org.ksoap2.transport.HttpTransportSE; 10 import org.xmlpull.v1.XmlPullParserException; 11 12 import android.app.Activity; 13 import android.os.AsyncTask; 14 import android.os.Bundle; 15 import android.view.View; 16 import android.widget.EditText; 17 import android.widget.TextView; 18 19 public class MainActivity extends Activity { 20 21 private EditText edit_poneNumber; 22 private TextView text_result; 23 private String QueryNumber; 24 25 //WSDL文档中的命名空间和方法 26 private static final String targetNameSpace = "http://WebXml.com.cn/"; 27 private static final String function = "getMobileCodeInfo"; 28 private static final String WSDL = "http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl"; 29 30 31 @Override 32 protected void onCreate(Bundle savedInstanceState) { 33 super.onCreate(savedInstanceState); 34 setContentView(R.layout.activity_main); 35 36 edit_poneNumber = (EditText)findViewById(R.id.edit_phone_sec); 37 text_result = (TextView)findViewById(R.id.result_text); 38 } 39 public void onQuety(View v) 40 { 41 QueryNumber = edit_poneNumber.getText().toString(); 42 if("".equals(QueryNumber.trim()) || QueryNumber.length() < 7) 43 { 44 edit_poneNumber.setError("输入有误"); 45 edit_poneNumber.requestFocus(); 46 text_result.setText(""); 47 return; 48 } 49 // 查询手机号码(段)信息 50 new getRemoteInfoTask().execute(); 51 } 52 /** 53 * 手机号段归属地查询 54 * 55 * @param phoneSec 手机号段 56 */ 57 public class getRemoteInfoTask extends AsyncTask<Void, Void , String> 58 { 59 @Override 60 protected String doInBackground(Void... arg0) { 61 // TODO 自动生成的方法存根 62 return getRemoteInfo(QueryNumber); 63 } 64 65 @Override 66 protected void onPostExecute(String result) 67 { 68 text_result.setText(result); 69 super.onPostExecute(result); 70 } 71 72 } 73 public String getRemoteInfo(String phoneSec) 74 { 75 String result = null; 76 SoapObject soapObject = new SoapObject(targetNameSpace, function); 77 soapObject.addProperty("mobileCode", QueryNumber); 78 soapObject.addProperty("userID", null); 79 SoapSerializationEnvelope envelop = new SoapSerializationEnvelope(SoapEnvelope.VER11); 80 envelop.dotNet = true; 81 envelop.setOutputSoapObject(soapObject);//或者envelop.bodyOut = soapObject; 82 HttpTransportSE httpSE = new HttpTransportSE(WSDL); 83 try { 84 httpSE.call(targetNameSpace+function, envelop); 85 SoapObject resultObj = (SoapObject) envelop.bodyIn; 86 result = resultObj.toString(); 87 } catch (IOException e) { 88 // TODO 自动生成的 catch 块 89 e.printStackTrace(); 90 } catch (XmlPullParserException e) { 91 // TODO 自动生成的 catch 块 92 e.printStackTrace(); 93 } 94 return result; 95 } 96 }