Android 通过广播来异步更新UI

时间:2023-03-09 23:49:14
Android 通过广播来异步更新UI

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

如今这个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,非常奇怪~~~求大神解答