ANR问题
1、先认识一下多线程异常
如果在主线程里面处理的事情过多,在执行过程中,某一阶段执行的任务过多,就会阻塞在一点,这时阻塞的时间长就会弹出继续等待还是退出应用!
ANR : Application Not Responding ,应用无响应
1 、 (Activity) 按键或者触摸事件在特定时间内 (5 秒 ) 无响应,主要是在加载UI界面时阻塞
2 、 BroadcastTimeout ,广播接收超时 (10 秒无响应 )
3 、 ServiceTimeout, 服务中 (20 秒无响应 )
// 常见的是前两种情况,第三种概率很小基本不存在
Thread+Handler
private void updateProgress() {
new Thread() {
@Override
public void run() {
while (progressBar.getProgress() < progressBar.getMax()) {
int p = progressBar.getProgress() + 5;
mHandler.obtainMessage(1, p).sendToTarget();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
Looper :负责线程中循环检测消息队列中是否有消息的一个对象,如果发现有消息,则移除消息给 Handler 处理
Handler : sendMessage postRunnable… 主要向它所关联的 Looper 所在的线程消息队列中压入消息对象,等到 Looper 发现消息移除消息出来然后给
handleMassage 方法处理
消息队列 MessageQueue :负责线程中消息的管理,先进先出
线程通讯机制
可以在子线程中通过 Looper 管理 Handler ,接收其他线程发来的消息
class A extends Thread {
A() {
super("线程A");
}
@Override
public void run() {
Log.e("m_tag", "启动");
//准备Looper
Looper.prepare();
//创建依赖于该线程Looper的Handler
aHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
Log.e("m_tag", "所在的线程" + getName() + "收到的消息" + msg.what);
if (msg.what == 102) {
//处理完事情停止Looper检测消息队列
Looper.myLooper().quit();
}
}
};
//启动Looper
Looper.loop();
Log.e("m_tag", "A线程结束");
}
}
class B extends Thread {
@Override
public void run() {
Log.e("m_tag", "B启动--休眠2S");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.e("m_Tag", "B线程发消息给A线程");
aHandler.sendEmptyMessage(101);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
aHandler.sendEmptyMessage(102);
}
}
使用
new A().start();
new B().start();
如果在其他线程中要关联主线程的 Looper 可以使用 Looper.getMainLooper() 得到 Looper 对象
mainHandler = new Handler(Looper.getMainLooper()){
@Override
public void handleMessage(Message msg) {
Log.e("m_tag", "所在的线程" + Thread.currentThread().getName()
+ "收到的消息:" + msg.what);
}
};
HandlerThread 的使用
HandlerThread t1 = new HandlerThread(" 线程 C");
t1.start();
// 基于 HandlerThread 创建 Handler
cHandler = new Handler(t1.getLooper()){
@Override
public void handleMessage(Message msg) {
Log.e("m_tag", "所在的线程" + Thread.currentThread().getName()
+ "收到的消息:" + msg.what);
Looper.myLooper().quit(); // 退出 Looper 的循环 , 结束线程
}
};
异步任务
可以继承 AsynTask 类实现异步任务,继承时 AsyncTask 后面的 3 个参数表示传入的参数类型,更新的参数类型,返回值类型
class MyTask extends AsyncTask<Object,Integer,Boolean>{
//子线程执行的方法
@Override
protected Boolean doInBackground(Object... params) {
int startProgress = (Integer) params[0];
while(startProgress < progressBar.getMax()){
startProgress +=2;
//更新,发布更新信息
publishProgress(startProgress);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return true;
}
//接收更新方法,是doInBackground方法中使用publishProgress方法时执行的
@Override
protected void onProgressUpdate(Integer... values) {
int p = values[0];
progressBar.setProgress(p);
}
//接收结果,就是doInBackground方法return的内容
@Override
protected void onPostExecute(Boolean aBoolean) {
if (null != aBoolean && aBoolean){
Toast.makeText(MainActivity.this,"更新完毕",Toast.LENGTH_LONG).show();
}else {
Toast.makeText(MainActivity.this,"更新失败",Toast.LENGTH_LONG).show();
}
}
}
使用:
new MyTask().execute(10);