Android 通过广播来异步更新UI

之前的项目里要做一个异步更新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没有输出,是最奇怪的~~~

时间: 2024-08-29 10:52:02

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

android异步更新UI界面的方法

在android平台下,进行多线程编程时,经常需要在主线程之外的一个单独的线程中进行某些处理,然后更新用户界面显示.但是,在主线线程之外的线程中直接更新页面显示的问题是:系统会报这个异常,android.view.viewroot$calledfromwrongthreadexception: only the original thread that created a view hierarchy can touch its views. (只有原始创建这个视图层次(view hierach

Android异步处理二:AsynTask介绍和使用AsyncTask异步更新UI界面

在上一篇(http://blog.csdn.net/xlgen157387/article/details/45269389)中介绍了使用Thread+Handler实现非UI线程更新UI界面的方法步骤,下边做一下如何同构AsyncTask异步任务来更新UI界面. (1)AsyncTask的介绍 通过上图中的AsyncTask的源码结构图可以看到,主要用于重载的方法是doInBackground(),onPreExecute().onPostExecute().onProgressUpdate(

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

Android异步处理二:使用AsyncTask异步更新UI界面 - lzc的专栏 - 博客频道 - CSDN.NET 在<Android异步处理一:使用Thread+Handler实现非UI线程更新UI界面>中,我们使用Thread+Handler的方式实现了异步更新UI界面,这一篇中,我们介绍一种更为简洁的实现方式:使用AsyncTask异步更新UI界面. 概述: AsyncTask是在Android SDK 1.5之后推出的一个方便编写后台线程与UI线程交互的辅助类.AsyncTask的

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

Android异步处理一:使用Thread+Handler实现非UI线程更新UI界面Android异步处理二:使用AsyncTask异步更新UI界面Android异步处理三:Handler+Looper+MessageQueue深入详解Android异步处理四:AsyncTask的实现原理 Android异步处理二:使用AsyncTask异步更新UI界面 概述: AsyncTask是在Android SDK 1.5之后推出的一个方便编写后台线程与UI线程交互的辅助类.AsyncTask的内部实现

android异步更新UI的几种方法

前言 ?我们知道在android开发中不能在非ui线程中更新ui,但是,有的时候我们需要在代码中执行一些诸如访问网络.查询数据库等耗时操作,为了不阻塞ui线程,我们时常会开启一个新的线程(工作线程)来执行这些耗时操作,然后我们可能需要将查询到的数据渲染到ui组件上,那么这个时候我们就需要考虑异步更新ui的问题了. android中有下列几种异步更新ui的解决办法: Activity.runOnUiThread(Runnable) View.post(Runnable) long) View.po

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

引言 在进行Winform程序开发需要进行大量的数据的读写操作的时候,往往会需要一定的时间,然在这个时间段里面,界面ui得不到更新,导致在用户看来界面处于假死的状态,造成了不好的用户体验.所以在大量数据操作的应用上,需要使用多线程来处理这种情况.在c#中使用多线程很方便只需要使用System.Threading.Thread的一个实例的Start方法就行了,但是如何实现多线程之间的交互就不是那么简单.本文实现了用子线程去处理数据,并实时更新主线程的ui状态了.下面就开始一步步的去实现异步线程更新

WPF中异步更新UI元素

XAML 界面很简单,只有一个按钮和一个lable元素,要实现点击button时,lable的内容从0开始自动递增. <Grid> <Label Name="lable_plus" Content="0"/> <Button Content="Button" Click="button_Click" Height="23" Name="button" Wid

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

Android的UI访问是没有加锁的,这样在多个线程访问UI是不安全的.所以Android中规定只能在UI线程中访问UI. 但是有没有极端的情况?使得我们在子线程中访问UI也可以使程序跑起来呢?接下来我们用一个例子去证实一下. 新建一个工程,activity_main.xml布局如下所示: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http:

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

引言 在进行Winform程序开发需要进行大量的数据的读写操作的时候,往往会需要一定的时间,然在这个时间段里面,界面ui得不到更新,导致在用户看来界面处于假死的状态,造成了不好的用户体验.所以在大量数据操作的应用上,需要使用多线程来处理这种情况.在c#中使用多线程很方便只需要使用System.Threading.Thread的一个实例的Start方法就行了,但是如何实现多线程之间的交互就不是那么简单.本文实现了用子线程去处理数据,并实时更新主线程的ui状态了.下面就开始一步步的去实现异步线程更新