Android的服务,其实就是能够实现程序在后台运行。适合执行那些不需要跟用户交互而且要求长期运行的任务。服务不依赖于任何用户界面,即使被切换到后台,或者被另外一个应用程序覆盖,服务仍然能保持正常运行。
但是,服务不是运行在一个独立的进程当中,而是依赖于创建服务时所依赖的应用程序的进程。如果一个应用程序进程被杀掉时,依赖该进程的服务也会停止运行。并且,服务不会自己开启线程,所有的代码都是默认在主线程中执行的。我们需要在服务内部手动创建子线程,要不然,就可能会出现主线程被阻塞的情况(比如,有一个访问网络的请求,如果不能即使在主线程中处理这个网络访问的请求,就有可能会阻塞主线程,影响用户体验。)。Android的UI是线程不安全的,即如果想要更新UI元素,更新界面,就必须在主界面中更新,否则就会出现异常。
综合以上原因,更新UI只能在主线程中更新,而此时访问耗时操作又不能再主线程中,只能在子线程中访问。于是,Android出现了一套异步消息处理机制。完美解决了在子线程中进行UI操作的问题,就是Handler,当子线程结束这种耗时的加载操作时,需要告诉主线程,我的工作完成了,然后获得加载完成的数据之后主线程才能更新UI,如果子线程没有通知主线程,主线程并不知道子线程什么时候结束加载任务,这样就无法及时的执行下去。Handler就是用于在线程之间传递消息的异步消息处理机制。
例子如下:
public class MainActivity extends AppCompatActivity implements View.OnClickListener{ private Button button; private TextView textView; private static final int UPDATE=1; private Handler handler=new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what){ case UPDATE: textView.setText("Hello,Hello,Hello,Hello!"); break; default: break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); button=(Button)findViewById(R.id.button); textView=(TextView)findViewById(R.id.textView); button.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()){ case R.id.button: new Thread(new Runnable() { @Override public void run() { Message message=new Message(); message.what=UPDATE; handler.sendMessage(message); } }).start(); break; default: break; } } }这样,点击按钮就会弹出设置的代码,xml文件就不添加了。
分析Android中的Handler异步消息处理机制:
主要有四部分,分别是Message,Handler,MessageQueue和Looper。
1.Message
Message是在线程之间传递的消息,它可以在内部携带少量的信息,用于在不同线程之间交换数据。message除了what字段外,还可以使用arg1跟arg2来携带一些整型的数据,可以使用obj字段携带一个Object对象。
2.Handler
Handler是处理者,主要是用于发送和处理消息的,发送消息一般是使用Handler的sendMessage()方法,而发出的消息经过一系列的处理后,最终会传递到Handler的handleMessage()中。
3.MessageQueue
MessageQueue是消息队列的意思,主要用于存放所有通过Handler发送的消息。这部分消息会一直存放在消息队列中,等待被处理,每个线程只有一个MessageQueue对象。
4.Looper是每个线程中的MessageQueue管家,Looper调用loop()方法之后,就会进入到一个无限循环当中,每次发现MessageQueue中存在一条信息的时候,就会将他取出来,并传递到Handler的handleMessage()中,每个线程也只是会有一个Looper对象。
所以,当进行异步消息处理的时候,首先需要在主线程中创建一个Handler对象,并重写handleMessage()方法,然后当想要在子线程中进行UI操作时,就创建一个message 对象,然后通过sendMessage()将这个消息发送出去。之后,这个消息会被添加到MessageQueue中等待被处理。然后Handler会一直尝试从MessageQueue中取出消息分发到Handler的handleMessage()中。最后Handler就在主线程中更新UI了。