Android平台叫用Web Service:引入線程

來源:互聯網
上載者:User

標籤:android平台   webservice   線程   runnable   

接上文

遺留問題

MainActivity的onCreate方法中如果沒有有這段代碼:

// 強制在UI線程中操作StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()       .detectDiskReads().detectDiskWrites().detectNetwork()        .penaltyLog().build());           StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()       .detectLeakedSqlLiteObjects().penaltyLog().penaltyDeath()        .build());

 

會報錯誤如下:

FATAL EXCEPTION:main

java.lang.NullPointerException

atcom.example.demoservice.MainActivity.getRemoteInfo(MainActivity.java:91)

atcom.example.demoservice.MainActivity$1.onClick(MainActivity.java:51)

 

這是因為android 3.0+以上 已經不建議在activity中添加耗時操作,要介面和資料脫離。4.0以上的通訊都必須放到線程裡去做,不能在UI線程。解決辦法是另起線程,如果一定要想在UI線程操作,就需要添加如上代碼。

 

顯然這樣做是不可取的,因為通訊消耗時間長,可能會讓使用者傻傻的等待,那麼接下來就通過引入線程來解決這個問題。


通過Runnable介面和Thread類建立線程

我們可以用Runnable介面和Thread類建立線程,從而捨棄強制使用UI主線程的方式,代碼如下(同時對代碼進行了整理,把nameSpace等變數抽出來)

public classMainActivity 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("");                               // 通過Runnable介面和Thread類 建立線程調用WebService                   newMyThread(nameSpace,methodName,endPoint,soapAction,                                                           params,vals).start();                       //將WebService返回的結果顯示在TextView中                    resultView.setText(getResult());             }         });     }        //通過Runnable介面和Thread類,得到線程傳回值privateString result; publicString getResult(){returnresult;}     private class MyThread extends Thread{     private String nameSpace;    private String methodName;    private String endPoint;    private String soapAction;        private ArrayList<String> params;        private ArrayList<Object> vals;           public MyThread(String nameSpace,  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;    }    @Overridepublicvoid run(){Log.i(TAG,"MyService線程ID:"+Thread.currentThread().getId());result= getRemoteInfo(nameSpace, methodName, endPoint,                                soapAction,params,vals);} }             /**     *@MethodName        : getRemoteInfo     *@Description        : 調用遠程webservice方法     * @param nameSpace     * @param methodName     * @param endPoint     * @param soapAction     * @param params     * @param vals     * @return     */    public String getRemoteInfo(StringnameSpace,  String methodName,                                   StringendPoint, String soapAction, ArrayList<String> params,                                   ArrayList<Object>vals) {           // 指定WebService的命名空間和調用的方法名         SoapObject rpc = newSoapObject(nameSpace, methodName);          //設定需調用WebService介面需要傳入的兩個參數mobileCode、userId         for (int i = 0; i < params.size();i++) {rpc.addProperty(params.get(i),vals.get(i));}          //產生調用WebService方法的SOAP請求資訊,並指定SOAP的版本         SoapSerializationEnvelope envelope =new SoapSerializationEnvelope(SoapEnvelope.VER10);          envelope.bodyOut = rpc;         // 設定是否調用的是dotNet開發的WebService //        envelope.dotNet = true;         // 等價於envelope.bodyOut = rpc;         envelope.setOutputSoapObject(rpc);          HttpTransportSE transport = newHttpTransportSE(endPoint);         try {             // 調用WebService             transport.call(soapAction,envelope);         } catch (Exception e) {             e.printStackTrace();         }          // 擷取返回的資料         SoapObject object = (SoapObject)envelope.bodyIn;                String result = "";        if (object != null) {               // 擷取返回的結果                result =object.getProperty(0).toString();         }         return result;    } } 


 

通過線程進行通訊,得到同樣結果



出現新的問題

可以發現,執行線程中需要線上程中返回一個值,通過在run()中儲存返回值,儲存返回值的變數應該是MainActivity的成員變數,然後在主線程中用一個get方法取得該值。

但是run何時完成是未知的,很可能當第一次點擊按鈕後,依然看不到結果,直到第二次或者更多才看到,所以我們需要一定的機制來保證。

 

而在Java se5就開始用Callable和Future來管理多線程了,可以解決這個問題,接下文。。。


源碼下載

http://download.csdn.net/detail/tcl_6666/7365341


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.