HandlerThread源码分析

HandlerThread(本质是Thread)
1.减轻主线程的压力,提高UI的流畅度
2.可以处理多个任务,开启一个线程起到多个线程的作用(looper共享)


public class HandlerThread extends Thread {
    int mPriority;
    Looper mLooper;

    public HandlerThread(String name) {
        super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }

    public HandlerThread(String name, int priority) {
        super(name);
        mPriority = priority;
    }

    //run方法里面的的内容在子线程中执行
    public void run() {
        mTid = Process.myTid();
        Looper.prepare(); //创建Looper放到ThreadLocal<Looper>里面
        synchronized (this) {
            //从ThreadLocal<Looper>中获取当前子线程的Looper
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }
    
    /**
     * 如果Looper没有创建好,会阻塞在这里
     */
    public Looper getLooper() {
        synchronized (this) {
            while (isAlive() && mLooper == null) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
        }
        return mLooper;
    }

    public boolean quit() {
        Looper looper = getLooper();
        if (looper != null) {
            looper.quit();
            return true;
        }
        return false;
    }
}

HandlerThread与Camera的能够Looper共享

需求:
打开相机
预览回调(编码)

异步任务的Looper,使用的MainLooper

public class AsyncTaskActivity extends Activity
 implements Callback {
    
    static final String TAG = "AsyncTaskActivity";
    
    Camera mCamera;
    SurfaceView surfaceView;
    SurfaceHolder surfaceHolder;
    byte[] buffers;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler_thread2);
        
        surfaceView = (SurfaceView) findViewById(R.id.surface_view);
        surfaceHolder = surfaceView.getHolder();
        surfaceHolder.addCallback(this);
    }
    
    class MyTask extends AsyncTask<Void, Void, Void> implements PreviewCallback{

        @Override
        protected Void doInBackground(Void... params) {
            //子线程中打开
            Log.d(TAG, Thread.currentThread().getName() + "_open");
            mCamera = Camera.open(CameraInfo.CAMERA_FACING_BACK);
            try {
                mCamera.setPreviewDisplay(surfaceHolder);
            } catch (IOException e) {
                e.printStackTrace();
            }
            Camera.Parameters parameters = mCamera.getParameters();
            //设置相机参数
            parameters.setPreviewSize(480, 320); //预览画面宽高
            mCamera.setParameters(parameters);
            //获取预览图像数据
            buffers = new byte[480 * 320 * 4];
            mCamera.addCallbackBuffer(buffers);
            mCamera.setPreviewCallbackWithBuffer(this);
            mCamera.startPreview();
            
            Log.d(TAG, Thread.currentThread().getName()+ "_doInBackground");
            
            return null;
        }

        //画面预览的回调
        @Override
        public void onPreviewFrame(byte[] data, Camera camera) {
            if(mCamera != null){
                mCamera.addCallbackBuffer(buffers);
                //主线程执行
                Log.d(TAG, Thread.currentThread().getName()+ "_onPreviewFrame");
            }
        }
        
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        new MyTask().execute();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, 
int width, int height) {
        
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        
    }

}

onPreviewFrame方法的回调实在相机类(Camera)里面的EventHandler.handleMessage方法中执行,onPreviewFrame方法调用跟EventHandler.handleMessage在同一个线程里面,而EventHandler.handleMessage调用所在线程是由Looper所在线程决定。
由于在上面的代码中没有调用Looper.prepare(), 结合Camera的构造函数可以知道会进入else if这个条件里面,此时Looper是在主线程的,因此上面代码中的onPreviewFrame方法在主线程调用的。

Camera(int cameraId) {
    ...
    Looper looper;
    //Looper.myLooper()不为空前提是调用了Looper.prepare()方法
    if ((looper = Looper.myLooper()) != null) {
        mEventHandler = new EventHandler(this, looper);
    } else if ((looper = Looper.getMainLooper()) != null) {//主线程
        mEventHandler = new EventHandler(this, looper);
    } else {
        mEventHandler = null;
    }
}

public class HandlerThreadActivity2 extends Activity implements Callback {

    static final String TAG = "jason";
    
    Camera mCamera;
    SurfaceView surfaceView;
    SurfaceHolder surfaceHolder;
    byte[] buffers;
    
    HandlerThread mHandlerThread = new HandlerThread("my_handlerthread");
    Handler subHandler;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_handler_thread2);
        
        surfaceView = (SurfaceView) findViewById(R.id.surface_view);
        surfaceHolder = surfaceView.getHolder();
        
        surfaceHolder.addCallback(this);
    }
    
    class MyTask implements Runnable, PreviewCallback{

        @Override
        public void run() {
            //打开相机
            //子线程中打开
            Log.d("jason", Thread.currentThread().getName() + "_open");
            mCamera = Camera.open(CameraInfo.CAMERA_FACING_BACK);
            try {
                mCamera.setPreviewDisplay(surfaceHolder);
            } catch (IOException e) {
                e.printStackTrace();
            }
            Camera.Parameters parameters = mCamera.getParameters();
            //设置相机参数
            parameters.setPreviewSize(480, 320); //预览画面宽高
            mCamera.setParameters(parameters);
            //获取预览图像数据
            buffers = new byte[480 * 320 * 4];
            mCamera.addCallbackBuffer(buffers);
            mCamera.setPreviewCallbackWithBuffer(this);
            mCamera.startPreview();
            
            Log.d(TAG, Thread.currentThread().getName()+ "_run");
        }
        
        @Override
        public void onPreviewFrame(byte[] data, Camera camera) {
            if(mCamera != null){
                mCamera.addCallbackBuffer(buffers);
                //子线程执行
                Log.d(TAG, Thread.currentThread().getName()+ "_onPreviewFrame");
            }
        }
        
    }
    

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        mHandlerThread.start();
        subHandler = new Handler(mHandlerThread.getLooper());
        subHandler.post(new MyTask());
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, 
int width, int height) {
        
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        
    }
}


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,634评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,951评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,427评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,770评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,835评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,799评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,768评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,544评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,979评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,271评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,427评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,121评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,756评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,375评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,579评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,410评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,315评论 2 352

推荐阅读更多精彩内容

  • 主目录见:Android高级进阶知识(这是总目录索引)[written by Ticoo] HandlerThre...
    ZJ_Rocky阅读 1,022评论 0 3
  • HandlerThread 顾名思义,HandlerThread它是一个Thread,是Google为提高开发者效...
    愤怒皮卡阅读 374评论 0 1
  • 概要介绍 HandlerThread是一种特殊的Thread,也就是有Looper的thread,既然有Loope...
    tmp_zhao阅读 493评论 0 1
  • 字体: 文本: 背景: 空间: 列表属性 表格属性: 盒子: 空间位置: 动画: 自定义字体: 字体格式: Tru...
    jhs1873阅读 410评论 0 0
  • 黛青月白待黄昏 斑驳叶影渐长如隙 晚空斜织一抹落霞 亦是飞鸟与潜鱼相留之信物 那一次偶然间四目相视相对 近在咫尺却...
    夢書客阅读 646评论 10 17