您的位置:首页 > 移动开发 > Android开发

Android平台调用Web Service:螺纹的引入

2015-10-24 18:52 513 查看
连接文本

剩下的问题

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;
}

@Override
publicvoid 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何时完毕是未知的,非常可能当第一次点击button后,依旧看不到结果,直到第二次或者很多其它才看到。所以我们须要一定的机制来保证。

而在Java se5就開始用Callable和Future来管理多线程了,能够解决问题。接下文。。。

源代码下载

http://download.csdn.net/detail/tcl_6666/7365341
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: