ANR错误之 keyDispatchingTimedOut

来源:互联网 发布:前后端数据交互方法 编辑:程序博客网 时间:2024/06/04 23:23

最近一个程序报错,查看LOG才知道是ANR错误,提示原因为  keyDispatchingTimedOut .

ANR的英文全称为Application not Response,就是说程序没有影响异常,此异常导致的根本原因有两种:

1、onCreate方法中执行时长超过5秒,程序其他操作不能进行

2、BroadcastReceiver接收广播时,超过10秒没有响应,其他操作无法进行

此两种异常为Android系统本身所定的处理时长,因此如果Activity中有一些费时操作,一定要避免。

可能触发ANR的情况

  1. 长时间的I/O处理,比如读写大文件,网络访问时造成的阻塞。
  2. 执行耗时的运算,Android默认为超过5000ms即5秒开始弹出ANR窗口,某些应用可能首次执行时没有缓存十分耗时,可以通过Splash播放闪屏Logo等方式来延缓加载。
  3. Service和appWidget中也要注意多线程的使用,除非它和Activity工作在不同的进程。

避免ANR的方法

1、用AsyncTask异步任务类处理(极力推荐),AsyncTask类为Android本身提供的,已经过封装,非常好用,示例代码如下:

private class GetDataTask extends AsyncTask{


@Override

protected void onPreExecute() {

// TODO Auto-generated method stub

super.onPreExecute();

}

 

@Override

protected String doInBackground(String... params) {

// TODO Auto-generated method stub

String result = null;

if("wx".equals(bind)){

final HttpClient httpClient = SSLSocketFactoryEx.getNewHttpClient();

String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="

+ Constants.weixinAPPID + "&secret="

+ Constants.weixinSecretKey + "&code=" +params[0]

+ "&grant_type=authorization_code";

final HttpGet get = new HttpGet(url);

HttpResponse httpResponse = null;

try {

httpResponse = httpClient.execute(get);

String json = EntityUtils

.toString(httpResponse.getEntity());

Log.e("hupeng", "===微信获取数据===" + json);

result=getWeixinUserInfo(json);

} catch (Exception e) {

e.printStackTrace();

} finally {

// 关闭连接 ,释放资源

httpClient.getConnectionManager().shutdown();

}

}else if("sina".equals(bind)){

mAccessToken = AccessTokenKeeper.readAccessToken(BandAccountActivity.this);

// 获取用户信息接口

sinaUid = Long.parseLong(mAccessToken.getUid());

sinaToken=mAccessToken.getToken();

Log.e("hupeng", "===新浪WeiboAuthListener===唯一id:"+sinaUid+"===mAccessToken==="+mAccessToken);

final HttpClient httpClient = SSLSocketFactoryEx.getNewHttpClient();

String url = "https://api.weibo.com/2/users/show.json?access_token="+sinaToken+"&uid="+sinaUid;

final HttpGet get = new HttpGet(url);

HttpResponse httpResponse = null;

try {

httpResponse = httpClient.execute(get);

result = EntityUtils.toString(httpResponse.getEntity());

Log.e("hupeng", "===新浪微博获取数据===" + result);

} catch (Exception e) {

e.printStackTrace();

handler.obtainMessage(9,"授权错误!").sendToTarget();

} finally {

// 关闭连接 ,释放资源

httpClient.getConnectionManager().shutdown();

}

}

return result;

}

 

@Override

protected void onPostExecute(String result) {

// TODO Auto-generated method stub

super.onPostExecute(result);

if("wx".equals(bind)){

JSONObject wxSendJson = new JSONObject();

JSONObject weixinJson;

try {

weixinJson = new JSONObject(result);

wxSendJson.put("bindtype", "2");// 1qq,2微信,3微博

wxSendJson.put("openid", weixinJson.get("openid"));// 用户唯一id

wxSendJson.put("access_tocken", wxToken);

wxSendJson.put("openkey", "");

wxSendJson.put("type", "1");

weixinOpenid=(String) weixinJson.get("openid");

wxSendJson.put("sessionid", Constants.userInfo.userSession);

} catch (JSONException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

Log.e("hupeng", "===微信用户信息===已成功向服务器发送微信绑定请求===" + result);

otherBind(wxSendJson, Constants.WEIXINLOGIN);// 绑定

}else if("sina".equals(bind)){

JSONObject json = new JSONObject();

try {

json.put("bindtype", "3");// 1qq,2微信,3微博

json.put("openid", sinaUid);// 用户唯一id

json.put("access_tocken", sinaToken);

json.put("openkey", "");

json.put("type", "1");

weiboOpenid=sinaUid+"";

json.put("sessionid", Constants.userInfo.userSession);

} catch (JSONException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

Log.e("hupeng", "===新浪用户信息===已成功向服务器发送微信绑定请求===" + json.toString());

otherBind(json, Constants.WEIBOLOGIN);// 绑定

}

}

 

 

}

2、单独开工作者线程,通过独立的Thread,如果线程比较多,可以用ExecutorService进行管理,也非常好用,示例代码如下:

ExecutorService pool = Executors.newFixedThreadPool(2); 
  //创建实现了Runnable接口对象,Thread对象当然也实现了Runnable接口 
  Thread t1 = new MyThread(); 
  Thread t2 = new MyThread(); 
  Thread t3 = new MyThread(); 
  Thread t4 = new MyThread(); 
  Thread t5 = new MyThread(); 
  //将线程放入池中进行执行 
  pool.execute(t1); 
  pool.execute(t2); 
  pool.execute(t3); 
  pool.execute(t4); 
  pool.execute(t5); 

3、耗时的操作尽量分段处理,使用类似状态机的方法,类似Symbian的活动对象将一个复杂的事情,分段执行,这是一种非常好的思路,可以将一大段非常长的耗时操作分为多段执行

4、UI线程中不要处理过多的内容,比如将一个5MB的文本,让TextView去setText,要知道这种UI操作,没有什么好方法去解决的,所以遇到UI中需要执行复杂的操作,可以参考上面3提到的分段处理方式。

还有个要注意的地方,当发生ANR错误时,具体代码出错记录会保存在data/anr/traces.txt里,可进行细节查看。

0 0
原创粉丝点击