首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >json字符串解析问题---有网和无网的情况下都要给用户友好的体验问题

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

作者头像
wust小吴
发布2019-07-08 16:11:50
7700
发布2019-07-08 16:11:50
举报
文章被收录于专栏:风吹杨柳风吹杨柳

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

首先程序跟踪是   :

11-03 13:30:30.134: E/AndroidRuntime(26947): java.lang.NullPointerException
11-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=value2
			UrlEncodedFormEntity 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")
			@Override
			public 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

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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2015年11月03日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档