之前的项目里要做一个异步更新UI的功能,可是结果出现了ANR,所以想写个demo来測试究竟是哪个地方出现了问题,结果发现原来的思路是没有问题,郁闷~~

如今这个demo 就是模拟项目里面 的步骤

1、接收到系统的广播(如今模拟为人工发送)

2、广播接收到后,handler通知异步线程从网上下载数据,是异步(模拟为sleep)

3、数据下载完后handler再通知UI更新



以下是基本的两个代码,可以正确执行

package com.example.testanr;

import android.support.v7.app.ActionBarActivity;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView; public class MainActivity extends ActionBarActivity {
public TextView hellworld = null;
public Button sendBroadcast = null;
public final static String MY_ACTION = "com.example.testanr.MY_ACTION";
public static int i = 0;
public Handler updateUI =new Handler(){ @Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
if(msg.arg1 ==0){
hellworld.setText("更新UI - "+ i);
i++;
}
} };
public Handler mHandler =new Handler(){ @Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
if (msg.arg1 == 1 ){
new Thread(new Runnable(){ @Override
public void run() {
// TODO Auto-generated method stub
System.out.println("Thread id is "+Thread.currentThread().getId()+",and Thread name is "+Thread.currentThread().getName());
try {
Thread.currentThread().sleep(15000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} Message msg =new Message();
msg.arg1 =0;
updateUI.sendMessage(msg);
} }).start(); }
} };
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); hellworld = (TextView)findViewById(R.id.hello_world);
sendBroadcast = (Button)findViewById(R.id.sendBroadcast);
//生成一个BroadcastReceiver对象
TestReceiver testReceiver = new TestReceiver(mHandler);
//生成一个IntentFilter对象
IntentFilter filter = new IntentFilter();
filter.addAction(MainActivity.MY_ACTION);
//将BroadcastReceiver对象注冊到系统其中
MainActivity.this.registerReceiver(testReceiver, filter);
System.out.println("Thread id is "+Thread.currentThread().getId()+",and Thread name is "+Thread.currentThread().getName());
sendBroadcast.setOnClickListener(new OnClickListener(){ @Override
public void onClick(View v) {
// TODO Auto-generated method stub
//发送广播
Intent intent = new Intent();
intent.setAction(MainActivity.MY_ACTION);
sendBroadcast(intent);
} });
} @Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
} @Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}

还有reciever

package com.example.testanr;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.Message; public class TestReceiver extends BroadcastReceiver {
public Handler handler;
public Message message = null;
public TestReceiver(Handler handler){
this.handler = handler; } @Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
//这里每次都要new,否者会报错
message = new Message();
message.arg1 = 1;
handler.sendMessage(message);
} }

如今才发现一个message是不能往MessageQueue里面发送多次的,否则会报这种错

java.lang.IllegalStateException: The specified message queue synchronization  barrier token has not been posted or has already been removed.

就说这个message的synchronization  barrier
token 已经发送过了的

可是项目里面的问题还没有解决,回头找出原因再发上来

我们知道ANR一般有三种类型

1:KeyDispatchTimeout(5 seconds) --主要类型

按键或触摸事件在特定时间内无响应

2:BroadcastTimeout(10
seconds)

BroadcastReceiver在特定时间内无法处理完毕

3:ServiceTimeout(20 seconds) --小概率类型

Service在特定的时间内无法处理完毕

所以原因还是应该是另外一种,可能没有模拟对

ANR的分析

怎样调查并解决ANR

1:首先分析log

2: 从trace.txt文件查看调用stack.

3: 看代码

4:细致查看ANR的成因(iowait?block?memoryleak?)

可是项目里面log没有输出,是最奇怪的~~~

//************************************9-29更新****************8

回去一看果然是一个message往looper的messagequeue发送了多次!!!可是log没有输出exception,并且为什么会导致ANR,非常奇怪~~~求大神解答

Android 通过广播来异步更新UI的更多相关文章

  1. Android异步更新UI的四种方式

    Android异步更新UI的四种方式 2015-09-06 09:23 segmentfault 字号:T | T 大家都知道由于性能要求,android要求只能在UI线程中更新UI,要想在其他线程中 ...

  2. Android异步处理系列文章四篇之二 使用AsyncTask异步更新UI界面

    Android异步处理一:使用Thread+Handler实现非UI线程更新UI界面Android异步处理二:使用AsyncTask异步更新UI界面Android异步处理三:Handler+Loope ...

  3. Android异步处理二:使用AsyncTask异步更新UI界面

    在<Android异步处理一:使用Thread+Handler实现非UI线程更新UI界面>中,我们使用Thread+Handler的方式实现了异步更新UI界面,这一篇中,我们介绍一种更为简 ...

  4. 使用AsyncTask异步更新UI界面及原理分析

    概述: AsyncTask是在Android SDK 1.5之后推出的一个方便编写后台线程与UI线程交互的辅助类.AsyncTask的内部实现是一个线程池,所有提交的异步任务都会在这个线程池中的工作线 ...

  5. Flutter学习笔记(31)--异步更新UI

    如需转载,请注明出处:Flutter学习笔记(31)--异步更新UI 大家都知道,子线程不能操作UI控件,在我们Android的日常开发中,经常会遇到网络请求数据通过线程间通信,将数据发送到UI线程中 ...

  6. 36.Android之多线程和handle更新UI学习

    android经常用到多线程更新UI,今天学习下. 首先布局比较简单: <?xml version="1.0" encoding="utf-8"?> ...

  7. Winform实现多线程异步更新UI(进度及状态信息)

    引言 在进行Winform程序开发需要进行大量的数据的读写操作的时候,往往会需要一定的时间,然在这个时间段里面,界面ui得不到更新,导致在用户看来界面处于假死的状态,造成了不好的用户体验.所以在大量数 ...

  8. Android中子线程真的不能更新UI吗?

    Android的UI访问是没有加锁的,这样在多个线程访问UI是不安全的.所以Android中规定只能在UI线程中访问UI. 但是有没有极端的情况?使得我们在子线程中访问UI也可以使程序跑起来呢?接下来 ...

  9. 在Android中实现service动态更新UI界面

    之前曾介绍过Android的UI设计与后台线程交互,据Android API的介绍,service一般是在后台运行的,没有界面的.那么如何实现service动态更新UI界面呢?案例:通过service ...

随机推荐

  1. 【Eclipse Plugin】SonarQube 启动报错

    由于近期,信息安全部在搞代码优化工作.所以,配合上边的工作需求,使用sonar对代码进行优化检测.在Eclipse上装Sonar很简单,只要在Eclipse Marketplace上面搜索“Sonar ...

  2. jQuery UI Widget 原理

    先看下代码的相关注释: /*! * jQuery UI Widget 1.8.1 * * Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/abo ...

  3. 数据结构C语言版 表插入排序 静态表

    数据结构C语言版 表插入排序.txt两个人吵架,先说对不起的人,并不是认输了,并不是原谅了.他只是比对方更珍惜这份感情./*  数据结构C语言版 表插入排序  算法10.3 P267-P270  编译 ...

  4. docker学习笔记7:发布镜像到docker hub上

    镜像创建好后,很重要的一个操作就是共享和发布.可以将自己创建的镜像发布到docker hub上,也可以发布到自己的私有docker hub上. 要想发布镜像到dokcer hub上,首先要在dokce ...

  5. AWVS介绍(转)

    使用AWVS对域名进行全局分析,深入探索: 首先,介绍一下AWVS这个工具. Acunetix Web Vulnerability Scanner(简称AWVS)是一款知名的网络漏洞扫描工具,它通过网 ...

  6. linux下java窗口,正确显示中文

    Tip1 1.在 JAVA_HOME/jre/lib/fonts/ 下建立个目录 fallback 2.在 fallback 里弄个中文字体最简单ln一下就好了 比如: ln -s /usr/shar ...

  7. iOS swift lazy loading

    Why bother lazy loading and purging pages, you ask? Well, in this example, it won't matter too much ...

  8. python读取文件内容方法

    1) readline 每次读一行,返回序列 2) readlines 一次全部读出,返回序列 3) numpy 的genfromtxt,返回为np的矩阵格式 import numpy as np f ...

  9. HDOJ1728 BFS【STL__queue_的应用】

    STL__queue_的应用 调用的时候要有头文件: #include<stdlib.h> 或 #include<cstdlib> + #include<queue> ...

  10. Android圆形图片自定义控件

    Android圆形图片控件效果图如下: 代码如下: RoundImageView.java package com.dxd.roundimageview; import android.content ...