Android平台调用Web Service:螺纹的引入
连接文本
剩下的问题
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
版权声明:本文博主原创文章,博客,未经同意不得转载。
相关文章
- Power Profiles for Android
- Android和iOS齐头并进 蚕食其他平台市场
- Android开发之PullToRefresh的Click点击事件的监听实现长按删除Item
- Android开发之调节屏幕亮度
- [bmgr]android应用数据备份以及还原
- Android handler机制
- android之surfaceview画图
- Android-----获取屏幕分辨率DisplayMetrics简介 .
- EasyRTMP Android安卓手机直播推流摄像头偏暗的问题解决
- 使用SAP云平台Android SDK创建Mobile应用
- 如何在Android平台上创建自定义的Cordova插件并使用SAP UI5消费
- cordova-plugin-ble-central插件1.2.2版android平台扫描出现Location Services are disabled
- Rockchip Android平台常用调试命令汇总
- Android平台上使用属性系统(property system)
- Android——控件显示和隐藏
- 基于NDK开发Android平台RTSP播放器
- 【Android 逆向】Android 逆向通用工具开发 ( Android 平台运行的 cmd 程序类型 | Android 平台运行的 cmd 程序编译选项 | 编译 cmd 可执行程序 )
- 【Android 逆向】修改运行中的 Android 进程的内存数据 ( 运行环境搭建 Android 模拟器安装 | 拷贝 Android 平台可执行文件和动态库到 /data/system )
- 如何成功实施SDL提供的官方Android平台Demo
- Android抽屉(SlidingDrawer --类似android通知栏下拉效果)
- RK3399平台开发系列讲解(项目实践篇)1.2、RK3399中的Android NNAPI
- Android程序性能优化——ANR、卡顿优化、内存优化、耗电优化、APK大小优化以及启动速度和实战项目