Android平臺調用Web Service:線程返回值
接上文
前文中的遺留問題
對於Java多線程的理解。我曾經只局限於實現Runnable接口或者繼承Thread類,然後重寫run()方法,最後start()調用就算完事。可是一旦涉及死鎖以及對共享資源的訪問和隨時監控線程的狀態和運行順序和線程返回值等就不行了。
Callable 和 Future 簡單介紹
Callable接口代表一段能夠調用並返回結果的代碼;Future接口表示是運行異步任務時的狀態、返回值等信息。所以說Callable用於產生結果,Future用於獲取結果。
1. Callable
Callable 是一個接口,它僅僅包括一個call()方法。Callable是一個返回結果而且可能拋出異常的任務。
為了便於理解,我們能夠將Callable比作一個Runnable接口,而Callable的call()方法則類似於Runnable的run()方法。
Callable的源代碼例如以下:
<span style="font-size:18px;">publi cinterface Callable<V> { V call() throws Exception; }</span>
2. Future
Future 是一個接口。它用於表示異步計算的結果。提供了檢查計算是否完畢的方法,以等待計算的完畢,並獲取計算的結果。
Future的源代碼例如以下:
<span style="font-size:18px;">public interface Future<V> { // 試圖取消對此任務的運行。 boolean cancel(boolean mayInterruptIfRunning) //假設在任務正常完畢前將其取消,則返回 true。 boolean isCancelled() //假設任務已完畢,則返回 true。 boolean isDone() //如有必要,等待計算完畢,然後獲取其結果。V get() throws InterruptedException,ExecutionException; //如有必要,最多等待為使計算完畢所給定的時間之後,獲取其結果(假設結果可用)。 V get(long timeout, TimeUnitunit) throws InterruptedException,ExecutionException, TimeoutException; }</span>
演示樣例的Callable和Future的基本使用方法
我們先通過一個演示樣例看看Callable和Future的基本使用方法
<span style="font-size:18px;">importjava.util.concurrent.Callable; importjava.util.concurrent.Future; importjava.util.concurrent.Executors; importjava.util.concurrent.ExecutorService; importjava.util.concurrent.ExecutionException; classMyCallable implements Callable { @Override public Integer call() throws Exception { int sum = 0; // 運行任務 for (int i=0; i<100; i++) sum += i; //return sum; return Integer.valueOf(sum); } } publicclass CallableTest1 { public static void main(String[] args) throws ExecutionException,InterruptedException{ //創建一個線程池 ExecutorService pool =Executors.newSingleThreadExecutor(); //創建有返回值的任務 Callable c1 = new MyCallable(); //運行任務並獲取Future對象 Future f1 = pool.submit(c1); // 輸出結果 System.out.println(f1.get()); //關閉線程池 pool.shutdown(); } }</span>
執行結果:
4950
結果說明:
在主線程main中,通過newSingleThreadExecutor()新建一個線程池。接著創建Callable對象c1。然後再通過pool.submit(c1)將c1提交到線程池中進行處理。而且將返回的結果保存到Future對象f1中。
然後,我們通過f1.get()獲取Callable中保存的結果;最後通過pool.shutdown()關閉線程池。
回到主題:調用查詢手機號歸屬地的webservice
事實上通過上面的簡單樣例,全然能夠將通過Runnable接口或者Thread類實現的線程代碼,改動成Callable和Future實現的線程。
<span style="font-size:18px;">public class Main Activity extends Activity { public static final String TAG ="webService_pj"; private EditText phoneSecEditText; private TextView resultView; private Button queryButton; @Override public void onCreate(BundlesavedInstanceState) { // StrictMode.setThreadPolicy(newStrictMode.ThreadPolicy.Builder() // .detectDiskReads().detectDiskWrites().detectNetwork() // .penaltyLog().build()); // // StrictMode.setVmPolicy(newStrictMode.VmPolicy.Builder() // .detectLeakedSqlLiteObjects().penaltyLog().penaltyDeath() // .build()); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); phoneSecEditText = (EditText)findViewById(R.id.phone_sec); resultView = (TextView)findViewById(R.id.result_text); queryButton = (Button)findViewById(R.id.query_btn); queryButton.setOnClickListener(newOnClickListener() { @Override public void onClick(View v) { Log.i(TAG,"MainActivity線程ID:"+Thread.currentThread().getId()); // 手機號碼(段) String phoneSec =phoneSecEditText.getText().toString().trim(); // 簡單推斷用戶輸入的手機號碼(段)是否合法 if("".equals(phoneSec) || phoneSec.length() < 7) { // 給出錯誤提示 phoneSecEditText.setError("您輸入的手機號碼(段)有誤。"); phoneSecEditText.requestFocus(); // 將顯示查詢結果的TextView清空 resultView.setText(""); return; } // 命名空間 String nameSpace = "http://WebXml.com.cn/"; // 調用的方法名稱 String methodName ="getMobileCodeInfo"; // EndPoint String endPoint = "http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx"; // SOAP Action String soapAction = "http://WebXml.com.cn/getMobileCodeInfo"; // method params and values ArrayList<String> params= new ArrayList<String>(); ArrayList<Object> vals =new ArrayList<Object>(); params.add("mobileCode"); params.add("userId"); vals.add(phoneSec); vals.add(""); //通過Callable和Future創建線程。調用WebService //創建有返回值的任務 CallableThread callable = newCallableThread(nameSpace,methodName,endPoint,soapAction,params,vals); // 創建一個線程池 ExecutorServiceexecutor=Executors.newCachedThreadPool(); //運行任務並獲取Future對象 Future<String>future = executor.submit(callable); try { //輸出結果 resultView.setText(future.get()); //關閉線程池 executor.shutdown(); }catch (InterruptedException e) { e.printStackTrace(); }catch (ExecutionException e) { e.printStackTrace(); } } }); } private class CallableThread implementsCallable<String> { private String nameSpace; private String methodName; private String endPoint; private String soapAction; private ArrayList<String> params; private ArrayList<Object> vals; public CallableThread(StringnameSpace, String methodName, StringendPoint, String soapAction, ArrayList<String> params,ArrayList<Object> vals){ this.nameSpace = nameSpace; this.methodName = methodName; this.endPoint = endPoint; this.soapAction = soapAction; this.params = params; this.vals = vals; } //須要實現Callable的Call方法 public String call() throws Exception{ // 這種方法的實現見上篇文章或者源代碼 return getRemoteInfo(nameSpace,methodName, endPoint, soapAction,params,vals); } } </span>
至此,Android調用Webservice就完美的完畢了。
源代碼下載
http://download.csdn.net/detail/tcl_6666/7365341
Android平臺調用Web Service:線程返回值