Android 多线程 (一)

本文介绍Android中ANR问题的原因及解决方案,探讨多线程间的通信机制,包括Handler、Looper的工作原理及其使用方法。
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);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值