这次项目,是关于小学生做试卷答题,但是后台没想到的是.net,需要用webservice soap协议,如此一来,以往的OKGO啊,OKHttp啊等一些网络请求框架均不能使用了。
这种项目一般还确实比较少,也已经很久没用android写过这个了,但是记得有ksoap的jar包来支持。ksoap3.6
不知道为什么最低分必须是2分。。。
好了,废话不多说,开始来搞吧!
首先明白几个东西,命名空间,方法名,EndPoint,SOAP Action。前两个简单,不必多少,而EndPoint就是WSDL地址去掉?wsdl之后的部分,Soap action 就是命名空间+方法名。而且如果可以参考我之前的文章,SoapUI这个工具的使用,来理解这些。
new Thread(new Runnable() {
@Override
public void run() {
// 创建HttpTransportSE对象, url timeOut
// AndroidHttpTransport httpTransportSE = new AndroidHttpTransport(baseURL, TIMEOUT);但是不建议用这个了已经过时了
HttpTransportSE httpTransportSE=new HttpTransportSE(endpoint);
// 创建SoapObject对象
SoapObject soapObject = new SoapObject(nameSpace, methodName);
PropertyInfo pi = new PropertyInfo();
pi.setName("key1");
pi.setValue("value1");
PropertyInfo pi1 = new PropertyInfo();
pi1.setName("key2");
pi1.setValue("value2");
soapObject.addProperty(pi);
soapObject.addProperty(pi1);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.bodyOut = soapObject;
envelope.dotNet = true;
envelope.setOutputSoapObject(soapObject);
try {
// 调用WebService
httpTransportSE.call(soapAction, envelope);
SoapPrimitive responseResult= (SoapPrimitive) soapEnvelope.getResponse();
String result =responseResult.toString();
} catch (Exception e) {
e.printStackTrace();
}
//下面这个方式不知道为什么拿不到了返回的数据了,就用了上面那个
// 获取返回的数据
//SoapObject object = (SoapObject) envelope.bodyIn;
// 获取返回的结果
//String result = object.getProperty(0).toString();
// 将WebService返回的结果显示在TextView中
textView.setText(result);
}
}).start();
但是每次请求都这样太麻烦了,后来看到网上人家封装的WebServiceUtil,但是已经不知道出处在哪了,但是还缺少header部分,但是我这边请求每次要带有特殊的header部分,以及回调,所以我改动了一些
所以我的封装如此了
public class WebServiceUtils {
// 含有3个线程的线程池
private static final ExecutorService executorService = Executors
.newFixedThreadPool(3);
/**
* @param url WebService服务器地址
* @param methodName WebService的调用方法名
* @param properties WebService的参数
* @param webServiceCallBack 回调接口
*/
public static void callWebService(String url, final String methodName,
HashMap<String, String> properties, Element[] header,
final WebServiceCallBack webServiceCallBack) {
// 创建HttpTransportSE对象,传递WebService服务器地址
final HttpTransportSE httpTransportSE = new HttpTransportSE(url);
// 创建SoapObject对象
SoapObject soapObject = new SoapObject(getServerIp(), methodName);
// SoapObject添加参数
if (properties != null) {
for (Iterator<Map.Entry<String, String>> it = properties.entrySet()
.iterator(); it.hasNext(); ) {
Map.Entry<String, String> entry = it.next();
soapObject.addProperty(entry.getKey(), entry.getValue());
}
}
// 实例化SoapSerializationEnvelope,传入WebService的SOAP协议的版本号
final SoapSerializationEnvelope soapEnvelope = new SoapSerializationEnvelope(
SoapEnvelope.VER11);
// 设置是否调用的是.Net开发的WebService
if (header == null) {
soapEnvelope.headerOut = MySoapHeader.getSoapHeader();
} else {
soapEnvelope.headerOut = header;
}
soapEnvelope.setOutputSoapObject(soapObject);
soapEnvelope.dotNet = true;
httpTransportSE.debug = true;
// 用于子线程与主线程通信的Handler
final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
// 将返回值回调到callBack的参数中
if(webServiceCallBack==null){
Log.i("tag","是null");
}
if (msg.what==0x1131){
webServiceCallBack.NetFailed();
}else {
webServiceCallBack.callBack((String) msg.obj);
}
}
};
// 开启线程去访问WebService
executorService.submit(new Runnable() {
@Override
public void run() {
SoapPrimitive result=null;
String handlerResult=null;
int whats=0;
// SoapObject resultSoapObject = null;
try {
httpTransportSE.call(getServerIp() + methodName, soapEnvelope);
if (soapEnvelope.getResponse() != null) {
result= (SoapPrimitive) soapEnvelope.getResponse();
handlerResult=result.toString();
// // 获取服务器响应返回的SoapObject
// resultSoapObject = (SoapObject) soapEnvelope.bodyIn;
// Log.i("tag","----------"+resultSoapObject.toString());
}else {
Log.i("tag","nu;;");
}
} catch (HttpResponseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
Log.i("tag","nu;;"+e.getMessage());
if (e.getMessage().contains("Network is unreachable")){
handlerResult="Network is unreachable";
whats=0x1131;
}
} catch (XmlPullParserException e) {
e.printStackTrace();
} finally {
// 将获取的消息利用Handler发送到主线程
mHandler.sendMessage(mHandler.obtainMessage(whats,
handlerResult));
}
}
});
}
/**
* @author xiaanming
*/
public interface WebServiceCallBack {
public void callBack(String result);
public void NetFailed();
}
}
在Activity中使用就这样即可:
HashMap hashMap = new HashMap();
hashMap.put("UserID", SharedPreferencesHelper.getString(getContext(), "user_id"));
hashMap.put("pageNo", pageNo);
hashMap.put("day", day);
hashMap.put("statu", statu);
hashMap.put("keyword", keyword);
WebServiceUtils.callWebService(getDataOperaNamespace(), GET_PAPER_LIST, hashMap, null, new WebServiceUtils.WebServiceCallBack() {
@Override
public void callBack(String result) {
if (null != result) {
Log.i("tag", "s========" + result);
}
}
@Override
public void NetFailed() {
}
});
我这里提取了我的header部分,上面的第四个参数null就代表是使用默认的header,header如此:
public class MySoapHeader {
public static Element[] getSoapHeader(){
Element[] header = new Element[1];
header[0] = new Element().createElement(getServerIp(), "MySoapHeader");
Element username = new Element().createElement(getServerIp(), "appKey");
username.addChild(Node.TEXT, "d095587f7482XXXXXXXXXXXXXX2fb");
header[0].addChild(Node.ELEMENT, username);
Element pwd = new Element().createElement(getServerIp(), "appSecret");
pwd.addChild(Node.TEXT, "85cXXXXXXXXXXXXXX9aeb");
header[0].addChild(Node.ELEMENT, pwd);
return header;
}
}
原以为就这样结束了,确实也就这样结束了,但是万万没想到,还有个问题,就是我在性能测试的时候,用LeakCanary进行测试的时候,发现内存泄漏了
测试的情景是当我发起网络请求的时候,但是网络情况不佳,还没有返回数据,我就关闭了这个页面,此外还导致了报错。这个LeakCanary用起来特别好,它会告诉你你是怎么内存泄漏的,就比如我这个,就是因为这个CallBack回调接口,是匿名内部类的引用,但是它持有着handler,就导致了内存泄漏。
肯定不能就这么任着,必须要解决啊。所以最后封装成如此:
public class WebServiceUtils {
// 含有3个线程的线程池
private static final ExecutorService executorService = Executors
.newFixedThreadPool(3);
static WebServiceCallBack webServiceCallBack;
public static void callWebService(Activity context,String url, final String methodName,
HashMap<String, String> properties, Element[] header,
WebServiceCallBack webServiceCallBacks) {
webServiceCallBack=webServiceCallBacks;
// 创建HttpTransportSE对象,传递WebService服务器地址
final HttpTransportSE httpTransportSE = new HttpTransportSE(url);
// 创建SoapObject对象
SoapObject soapObject = new SoapObject(getServerIp(), methodName);
// SoapObject添加参数
if (properties != null) {
for (Iterator<Map.Entry<String, String>> it = properties.entrySet()
.iterator(); it.hasNext(); ) {
Map.Entry<String, String> entry = it.next();
soapObject.addProperty(entry.getKey(), entry.getValue());
}
}
// 实例化SoapSerializationEnvelope,传入WebService的SOAP协议的版本号
final SoapSerializationEnvelope soapEnvelope = new SoapSerializationEnvelope(
SoapEnvelope.VER11);
// 设置是否调用的是.Net开发的WebService
if (header == null) {
soapEnvelope.headerOut = MySoapHeader.getSoapHeader();
} else {
soapEnvelope.headerOut = header;
}
soapEnvelope.setOutputSoapObject(soapObject);
soapEnvelope.dotNet = true;
httpTransportSE.debug = true;
// 用于子线程与主线程通信的Handler
final MyHandler mHandler = new MyHandler(context) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
// 将返回值回调到callBack的参数中
if (weakReference.get()!=null){
Log.i("tag","hello");
if (msg.what == 0x1131) {
webServiceCallBack.NetFailed();
} else {
webServiceCallBack.callBack((String) msg.obj);
}
}else {
Log.i("tag","亲,已经销毁了");
}
}
};
// 开启线程去访问WebService
executorService.submit(new Runnable() {
@Override
public void run() {
SoapPrimitive result=null;
String handlerResult=null;
int whats=0;
// SoapObject resultSoapObject = null;
try {
httpTransportSE.call(getServerIp() + methodName, soapEnvelope);
if (soapEnvelope.getResponse() != null) {
result= (SoapPrimitive) soapEnvelope.getResponse();
handlerResult=result.toString();
// // 获取服务器响应返回的SoapObject
// resultSoapObject = (SoapObject) soapEnvelope.bodyIn;
// Log.i("tag","----------"+resultSoapObject.toString());
}else {
Log.i("tag","nu;;");
}
} catch (HttpResponseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
Log.i("tag","nu;;"+e.getMessage());
if (e.getMessage().contains("Network is unreachable")){
handlerResult="Network is unreachable";
whats=0x1131;
}
} catch (XmlPullParserException e) {
e.printStackTrace();
} finally {
// 将获取的消息利用Handler发送到主线程
mHandler.sendMessage(mHandler.obtainMessage(whats,
handlerResult));
}
}
});
}
static class MyHandler extends Handler{
WeakReference<Activity> weakReference;
public MyHandler(Activity context){
weakReference =new WeakReference<Activity>(context);
}
}
/**
* @author xiaanming
*/
public interface WebServiceCallBack {
public void callBack(String result);
public void NetFailed();
}
public static void cancelCall(){
webServiceCallBack=null;
}
}
在activity中这样
@Override
protected void onDestroy() {
super.onDestroy();
WebServiceUtils.cancelCall();
}
看,没有泄漏了
先这样吧,我觉得我这个里面还有很多的问题,或者有更好的解决方案,你们可以留言给我。谢谢了
此外再向大家推荐一个超好用的xml转json的工具,这样,xml转json,再gson转对象,太方便。
JSONObject jsonObject = XML.toJSONObject(result);
用的jar包在这 java-json.jar
本人个人原创,如有雷同,纯属巧合,或者与本人联系,做改动。请转载或者CV组合标明出处,谢谢!(如有疑问或错误欢迎指出,本人QQ:752231513)