最近遇到这样的问题,就是加了 网络检查 但是如果当前的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
其实说这么多 关键的地方就是 空指针导致 程序直接停止运行了,只要你把这个异常捕捉到就行,