博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android 通过广播来异步更新UI
阅读量:6161 次
发布时间:2019-06-21

本文共 4787 字,大约阅读时间需要 15 分钟。

之前的项目里要做一个异步更新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一般有三种类型

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

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

2BroadcastTimeout(10 seconds)

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

3ServiceTimeout(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,非常奇怪~~~求大神解答

转载地址:http://zwefa.baihongyu.com/

你可能感兴趣的文章
Spring如何处理线程并发
查看>>
linux常用命令(用户篇)
查看>>
获取组件的方式(方法)
查看>>
win2008 server_R2 自动关机 解决
查看>>
我的友情链接
查看>>
在C#调用C++的DLL简析(二)—— 生成托管dll
查看>>
Linux macos 常用终端操作
查看>>
企业网络的管理思路
查看>>
Linux磁盘分区与挂载
查看>>
J2se学习笔记一
查看>>
DNS视图及日志系统
查看>>
老李分享:Android性能优化之内存泄漏 3
查看>>
mysql命令
查看>>
来自极客标签10款最新设计素材-系列七
查看>>
极客技术专题【009期】:web技术开发小技巧
查看>>
PHP 简单计算器代码实现
查看>>
正则表达式的知识普及
查看>>
docker使用笔记
查看>>
华为eNSP模拟器上实现FTP服务
查看>>
【全球AI人才排行榜】美国第一,中国仅排名第7
查看>>