json字符串解析问题---有网和无网的情况下都要给用户友好的体验问题

来源:互联网 发布:html5 javascript 编辑:程序博客网 时间:2024/05/18 02:31

最近遇到这样的问题,就是加了  网络检查  但是如果当前的app在运行的时候没有退出,同时这个时候断网了,如果再请求,我忘记了再次去检查网络,如果加了网络检查就不需要看下面的东西,如果没有加网络检查的话,那么就出现下面的bug


首先程序跟踪是   :

11-03 13:30:30.134: E/AndroidRuntime(26947): java.lang.NullPointerException11-03 13:30:30.134: E/AndroidRuntime(26947): at org.json.JSONTokener.nextCleanInternal(JSONTokener.java:116)11-03 13:30:30.134: E/AndroidRuntime(26947): at org.json.JSONTokener.nextValue(JSONTokener.java:94)11-03 13:30:30.134: E/AndroidRuntime(26947): at org.json.JSONObject.<init>(JSONObject.java:155)11-03 13:30:30.134: E/AndroidRuntime(26947): at org.json.JSONObject.<init>(JSONObject.java:172)

上面的问题我相信大家经常碰见,就是没有网的时候服务器上返回的数据为空,json解析的时候自然就会报这样的错,而且是直接弹出   

当前程序已停止运行


现在首先说下我的网络访问---json解析---在返回给handler处理的机制:


网络访问应该大家都是一样的,就是一个post请求  get这样就不说了:

</pre><pre name="code" class="java">private static HttpClient client = new DefaultHttpClient();public String getJsonString(String url) {String result = "";String line = "";InputStream is = null;try {HttpClient httpclient = new DefaultHttpClient();httpclient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 5000);httpclient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 5000);HttpResponse response = httpclient.execute(new HttpGet(url));is = response.getEntity().getContent();if (is != null) {BufferedReader rd = new BufferedReader(new InputStreamReader(is));while ((line = rd.readLine()) != null) {result += line;}is.close();}return result;} catch (Exception e) {e.printStackTrace();}return null;}public String doPost(String url, ArrayList<BasicNameValuePair> data) {try {// UrlEncodedFormEntity这个类是用来把输入数据编码成合适的内容// 两个键值对,被UrlEncodedFormEntity实例编码后变为如下内容:param1=value1¶m2=value2UrlEncodedFormEntity entity = new UrlEncodedFormEntity(data,HTTP.UTF_8);// 首先将参数设置为utf-8的形式,String result = "";// 向服务器请求之后返回的数据结果HttpClient httpClient = new DefaultHttpClient();// 申明一个网络访问客户端HttpPost post = new HttpPost(url);// post方式post.setEntity(entity);// 带上参数HttpResponse httpResponse = httpClient.execute(post);// 响应结果if (httpResponse.getStatusLine().getStatusCode() == 200) {// 如果是200 表示成功result = EntityUtils.toString(httpResponse.getEntity());// 把结果取出来 是一个STRING类型的}return result;} catch (Exception e) {return null;}}

把上面的代码放到一个工具类里面   要做的时候自己调用就行


现在就是访问有两种写法:

一种是直接调用上面的方法,得到返回的数据,再专门做一个json解析的工具类   推荐这种方法,避免很多错误

第二种是直接写个方法,在方法里面调用上面的请求代码,返回直接把json解析也在这里面做了,直接把需要的结果给程序就行,这样在handler里面避免很多业务处理,

比如我们需要判断状态,根据状态做不同的事,如果你的目的明确,减少程序里面各种代码,这种方法也是可以的,但是就是好多  空指针的错误会般绕着你啊


我的错误就是出现在第二种方法里面,没有网的时候,报 空指针错误,这种错误会直接让当前的 程序停止运行,必须要处理掉

下面的代码里面有注释,避免空指针错误  


public static ArrayList<Object> getBigProjectInfoData(String URL, ArrayList<BasicNameValuePair> data) {ArrayList<Object> list = new ArrayList<Object>();//返回结果自己定义的,很多时候是返回ArrayList 有的时候返回map更方便,看自己的需要把HttpTools httptools = new HttpTools();String result = httptools.doPost(URL, data);if(result == null){//这里的代码是必须要的,避免空指针错误,否则程序直接退出,return null;}if{try {//解析json数据 涉及到多层解析json我这里就不写了,其实网上有工具能够解析到三层,//我一直要求后台返回的json不要超过3层,越多解析起来越麻烦,} catch (JSONException e) {}return list;}}

接下来说第一种方法,第一种方法就是把网络访问和json解析分离了,我推荐大家使用这种,

你必须自己再写一个json解析工具,因为调用异步进程请求网络的时候返回的就是一个json字符串,string类型的


下面是异步线程的代码:

new Thread(new Runnable() {@SuppressWarnings("deprecation")@Overridepublic void run() {Message msg = Message.obtain();ArrayList<BasicNameValuePair> data = new ArrayList<BasicNameValuePair>();//用于post请求的键值对,前面的参数是键,后面的是值if(netCheck.isNetworkConnected() == true){//如果有网,就执行网络请求,如果没有网就不做网络请求msg.obj = HttpTools.doPost(Constants.URL_ALL_MYWORKER_INFO,data);//调用URL  获取数据集msg.what = INIT;//给handler传回的类型}else{msg.obj = "network is failed";msg.what = NOTNETWORK;}getDateHandler.sendMessage(msg);//执行传递}}).start();


其实这里面已经加上了检查网络的情况:

然后把服务器返回的东西交给handler处理,这个时候有人肯定说  你这种情况也有可能是返回null啊,只要你保证后台每次网络请求不管是失败还是成功,都返回状态码就可以避免空指针的问题


在handler里面你不是处理msg.obj了吗,然后交给专业的解析工具处理,或者是自己写处理工具都行

下面的代码是自己写处理json

public ArrayList<TiebaModule> getTiebaModule(String jsonStr){try{ArrayList<TiebaModule> result = new ArrayList<TiebaModule>();JSONArray jArray = new JSONArray(jsonStr);JSONObject jsonObj;for(int i = 0; i < jArray.length() ; i++){TiebaModule module = new TiebaModule();jsonObj = jArray.getJSONObject(i);module.setModuleId(jsonObj.optString("moduleid"));//module.setModuleImg(jsonObj.optString("moduleimg"));//module.setModuleName(jsonObj.optString("modulename"));//result.add(module);}return result;}catch(Exception e){return null;}}

这里面换成了如果遇到  空指针 或者其他的异常情况,直接返回null


其实说这么多  关键的地方就是  空指针导致  程序直接停止运行了,只要你把这个异常捕捉到就行,

0 0
原创粉丝点击