android 4.0 子线程联网,Android4.0网络操作必须放在子线程中

好久没写技术博客了。关于为什么这么久没写,是因为写伤了。写过几篇博客后,深刻感觉到要把博客写好是一件很累的事情,花的时间也肯定不会少。记得前段时间写Android中Activity四种启动模式和taskAffinity属性详解这篇博客,前前后后写了一个星期,从那之后真有点怕写这么长的博客了。所以, 以后尽可能不写这种总结性的,篇幅较长的博客,因为自己水平真的有限,写这种长博客太累, 写了之后别人还不见得有耐心读完。另一方面, 写这种长博客花的时间和精力太多, 很累人,并且只能下了班之后抽晚上的时间写。由于不满足自己现在的水平,我业余时间最想做的事是多看书,多补充知识。少写博客,要写的话也是那种短的博客, 可能是工作中解决了一个问题,并且认为这个问题很有代表性,就会整理一下写成一小篇;也可能平时写了一个小demo,能说明一些问题,也会写成短篇博客。

最近一直在做一个移动办公的项目,今天写登陆验证这块的时候被一个问题给缠住了。下面会通过这个简单的小问题来引出这篇文章的主题

Android4.0中网络操作必须放在子线程中

这个登陆验证是一个简单的不能再简单的登陆验证了, 就是把用户名和密码还有其他一些信息以参数的形式发送到后台, 然后读出后台返回的验证结果。在进行http请求时,使用的是标准的UrlConnection类,下面是这个功能的代码:

private static boolean userLoginCheck1( Context context){

//设置登录验证的各项参数

List params = new LinkedList();

params.add(new BasicNameValuePair("yhid", userName));

params.add(new BasicNameValuePair("yhkl", passwd));

params.add(new BasicNameValuePair("sbid", DeviceTool.getDeviceId(context)));

params.add(new BasicNameValuePair("clientIp", IPTool.getPsdnIp()));

params.add(new BasicNameValuePair("ywxtbm", "BGPTNEW"));

params.add(new BasicNameValuePair("ywxtmc", "办公平台升级"));

URL url = null;

StringBuilder sb = new StringBuilder();

BufferedReader reader = null;

try{

//设置url地址

url = new URL(URLConstant.USER_LOGIN_CHEAK_ADDRESS);

String paramString = URLEncodedUtils.format(params, "GBK");//请求参数编码为GBK

byte[] dataToSend = paramString.getBytes();//post请求中的实体数据

HttpURLConnection connection = (HttpURLConnection) url.openConnection();

connection.setRequestMethod("POST");

connection.setDoOutput(true);

connection.setConnectTimeout(5000);

connection.setRequestProperty("Content-Length", String.valueOf(dataToSend.length));

connection.getOutputStream().write(dataToSend);//发送数据

if(connection.getResponseCode() != 200){

Log.i("eSDK", "验证登陆请求响应码不是200");

return false;

}

InputStream stream = connection.getInputStream();

reader = new BufferedReader(new InputStreamReader(stream, "GBK"));

String lines = "";

while ((lines = reader.readLine()) != null){

sb.append(lines);

}

Log.i("eSDK", "login cheak response: " + sb.toString());

//对返回的数据进行判断, 以验证是否可以登陆

return "验证成功".equals(sb.toString());

}catch (Exception e){

Log.i("eSDK", "logincheck fail" );

return false;

}finally{

if (reader != null){

try{

reader.close();

}

catch (IOException e){}

}

}

}

做过网络编程的, 都会对这段代码非常非常熟悉,就是一个标准的http请求。但是我却在这里卡住了,程序逻辑没错啊, 却怎么也通不过,每次单步跟踪到

connection.getOutputStream().write(dataToSend);

这句代码就会抛出异常,真是被搞的很郁闷。最后将这段代码拿到java工程中运行, 没有任何问题。这时,我意识到自己犯了一个愚蠢的错误。由于是边写代码边测试,所以没有把这个方法放到子线程中执行。android2.3中只是建议把网络操作放到子线程中,而android4.0要求必须把和网络相关的操作放到子线程中。其实这个知识点我是知道的,因为我不是第一次犯这种错误,但是出现问题时却没往这个方面思考。所以:

当你在Android4.0中调用和网络相关的api时总是不能成功,那么检查一下是否在子线程中调用的;

当你在Android4.0中写以上类似的方法时,如果总是在connection.getOutputStream()处抛异常,那么检查一下是否在子线程中调用;

Android4.0中的这一个特性很坑爹,因为如果你在主线程中进行网络操作,它只是让你失败, 并不会给出任何通知,所以如果不知道这个特性,或者是没考虑到这个方面,那么解决问题是很费时间的!个人认为android有必要在检测到主线程中有网络操作时,抛出运行时异常,比如可以定义一个RunInWrongThreadException。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值