Handler Looper

从注释看起
的源码只有不到800行,而且大多数代码相对来说还是比较好理解的,尤其是相对于其他更加接近底层的代码来说,在看源码时候有一点挺重要的就是不要忽略注释的作用,类开头有这么几行注释:
There are two main usesfor a Handler: (1) to schedule messages andrunnables to be executed as some point in the future; and (2) to enqueuean action to be performed on a different thread than your own.
归纳一下就是:
回顾一下我们为什么要用:
在中,当要更新UI的时候,我们必须要在主线程中进行更新,原因时当主线程被阻塞了5s以上就会出现ANR异常,会导致程序崩溃 。所以一些耗时的操作必须要放在子线程中,但是在子线程中又不能做更新UI的操作,所以为了解决这个问题,设计了机制 。
这么一对比,很容易的印证了这段话:使一个动作进入队列在另一个线程中执行:这不就是异步执行耗时任务么;安排消息和任务在将来的某一个点执行:联想一下之类的延时操作的方法,或者给出一个很常见的例子,比如说引导页延时启动:
new Handler().postDelayed(new Runnable() {@Overridepublic void run() {Log.d("ThreadName 1",Thread.currentThread().getName());//第一次登陆扫描本地音乐if (SPUtils.getValue(SplashActivity.this, "isFirst", "First", true)) {new Thread(new Runnable() {@Overridepublic void run() {//耗时操作//清空表Log.d("ThreadName 2",Thread.currentThread().getName());DataSupport.deleteAll(MusicInfoDetail.class);MusicUtils.scanMusic(SplashActivity.this, musicInfo);DataSupport.saveAll(musicInfo);SPUtils.putValue(SplashActivity.this, "isFirst", "First", false);}}).start();}, 2000);
这里是我自己的Demo里面的一部分代码,这里使用延时2s启动,然后在子线程执行更新数据库的操作,很好的印证了上面两点 。
创建
在上一篇文章机制从入门到放弃(一)里面我们已经演示了两种创建的方法并且给出了部分实际操作的代码,但是都是在主线程也就是UI线程创建的,我们可以尝试一下在子线程中创建:
public class MainActivity extends AppCompatActivity {private Handler mainHandler;private Handler childHandler;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mainHandler=new Handler();new Thread(new Runnable() {@Overridepublic void run() {childHandler=new Handler();}}).start();}}
运行一下,果不其然代码蹦了:

Handler Looper

文章插图
Crash
报错信息:
java.lang.RuntimeException: Can't create handler inside thread that hasnot called Looper.prepare()
告诉我们说在里面创建需要调用.( ),那把这一句加上试试:
public class MainActivity extends AppCompatActivity {private Handler mainHandler;private Handler childHandler;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);mainHandler=new Handler();new Thread(new Runnable() {@Overridepublic void run() {Looper.prepare();childHandler=new Handler();}}).start();}}
Handler Looper

文章插图
运行结果
果然很成功的运行了,但是这是为什么,来看一下的源码:
这里提供一个简便的方法,为了快速找到原因可以在打开的源码(我这里使用查看)里使用ctrl+f快捷键搜索.( )出现的地方:
public Handler(Callback callback, boolean async) {if (FIND_POTENTIAL_LEAKS) {final Class