Android Service
Android 多线程机制
异步消息处理机制使用
Message、Handler、MessageQueue、Looper,相关源码路径在 frameworks/base/core/java/android/os/
示例代码(主线程中使用 Handler)
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private TextView text;
public static final int UPDATE_TXT = 1;
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what){
case UPDATE_TXT:
text.setText("haha");
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
text = (TextView) findViewById(R.id.text);
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(this);
}
@Override
public void onClick(View v){
switch (v.getId()){
case R.id.button:
new Thread(new Runnable() {
@Override
public void run() {
//这里不使用 new Message 方式进行创建一个 Message。
Message message = Message.obtain();
message.what = UPDATE_TXT;
handler.sendMessage(message);
//text.setText("haha");
}
}).start();
break;
default:
break;
}
}
}
大致小结一下,说了那么多相信大家已经对 Handler 的作用比较熟悉了,其实也是一个线程间通信的机制,主要用于在子线程中对 UI 进行实时更新,因为我们都知道 UI 操作一般都是线程不安全的,一些耗时操作应该放在子线程中进行处理,而 UI 更新代码必须放置在主线程中。使用方法还是很简单 new Thread()创建线程,线程中做的操作:(1)填充 Message (2)调用 handler 的 sendMessage 函数给 handleMessage 函数进行处理。使用起来还是很方便的,但是作为从底层爬上来的码农,总觉得不够味,MessageQueue 在哪?Looper 在哪?下面就来简要分析一下整个流程。
异步消息处理分析
- Handler 的构造函数
frameworks/base/core/java/android/os/Handler.java
,获取 Looper 对象,从 Looper 中读取 mQueue(MessageQueue)
public Handler() {
this(null, false);
}
.......
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&
(klass.getModifiers() & Modifier.STATIC) == 0) {
Log.w(TAG, "The following Handler class should be static or leaks might occur: " +
klass.getCanonicalName());
}
}
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
......
- 问题来了,上面的代码中 Handler 的构造函数里面有取出 Looper 对象,那 Looper 是什么时候创建的呢?这里直接给出答案了,如果在创建 Handler 的时候是放在主线程中,activity 会自动帮你创建一个 looper 对象,代码路径
frameworks/base/core/java/android/app/ActivityThread.java
中会创建 Looper 对象,这里就不再深入分析了,直接给出 Looper 的构造函数。
public static void main(String[] args) {
...
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
...
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
- Looper.loop()函数会创建一个死循环,queue.next() 取出 MessageQueue 中的数据,再调用 dispatchMessage 进行对 Message 进行处理的操作
for (;;) { Message msg = queue.next(); // might block if (msg == null) { // No message indicates that the message queue is quitting. return; } // This must be in a local variable, in case a UI event sets the logger final Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); } final long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs; final long traceTag = me.mTraceTag; if (traceTag != 0 && Trace.isTagEnabled(traceTag)) { Trace.traceBegin(traceTag, msg.target.getTraceName(msg)); } final long start = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis(); final long end; try { msg.target.dispatchMessage(msg); end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis(); } finally { if (traceTag != 0) { Trace.traceEnd(traceTag); } }
- Message 的构造函数,代码路径
frameworks/base/core/java/android/os/Message.java
,这里不直接 new 的原因注释也说的很明白,从global pool 中取出 Message ,避免内存申请释放问题.
/**
* Return a new Message instance from the global pool. Allows us to
* avoid allocating new objects in many cases.
*/
public static Message obtain() {
synchronized (sPoolSync) {
if (sPool != null) {
Message m = sPool;
sPool = m.next;
m.next = null;
m.flags = 0; // clear in-use flag
sPoolSize--;
return m;
}
}
return new Message();
}
- handler 的 sendMessage 方法,最后会调用 sendMessageAtTime 方法,这里先获取 mQueue(在之前调用 Handler 构造函数的时候,从Looper获取的),之后调用 enqueueMessage 将 msg 入栈,enqueueMessage 最后会调用
frameworks/base/core/java/android/os/MessageQueue.java
里面的
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
- 最后再来看一下 Handler 的 handleMessage 方法,Handler 类中的函数是一个空函数,所以需要在子类中实现 handleMessage 用于处理 Message。
- 关于在子线程中创建 Handler 就需要自己手动去创建 looper,下面给出的是示例代码,相关操作和在主线程中创建是类似的,只是 Looper 的创建不在是由Android帮你创建,而是自己手动去创建了。
/**
* Class used to run a message loop for a thread. Threads by default do
* not have a message loop associated with them; to create one, call
* {@link #prepare} in the thread that is to run the loop, and then
* {@link #loop} to have it process messages until the loop is stopped.
*
* <p>Most interaction with a message loop is through the
* {@link Handler} class.
*
* <p>This is a typical example of the implementation of a Looper thread,
* using the separation of {@link #prepare} and {@link #loop} to create an
* initial Handler to communicate with the Looper.
*
* <pre>
* class LooperThread extends Thread {
* public Handler mHandler;
*
* public void run() {
* Looper.prepare();
*
* mHandler = new Handler() {
* public void handleMessage(Message msg) {
* // process incoming messages here
* }
* };
*
* Looper.loop();
* }
* }</pre>
*/
AsyncTask
本质使用的还是异步消息来实现的一种多线程通信机制,在使用 AsyncTask 时,需要实现 AsyncTask 这个抽象类。需要重写的方法:onPreExecute、doInBackgroud、onProgressUpdate、onPostExecute
服务的基本用法
继承类 Service。我们需要重写 onCreate、onStartCommand、onDestory、onBinder(唯一一个抽象方法,必须实现)
代码示例
public class MyService extends Service {
private DownloadBinder mBinder = new DownloadBinder();
class DownloadBinder extends Binder{
public void startDownload(){
Log.d("MyService","startdownload");
}
public int getProgress(){
Log.d("MyService","getProgress");
return 0;
}
}
@Override
public IBinder onBind(Intent intent){
return mBinder;
}
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
借助 Intent 在 activity 中启动 service
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private MyService.DownloadBinder downloadBinder;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
downloadBinder = (MyService.DownloadBinder)service;
downloadBinder.startDownload();
downloadBinder.getProgress();
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button startService = (Button) findViewById(R.id.start_Service);
Button stopService = (Button) findViewById(R.id.stop_Service);
startService.setOnClickListener(this);
stopService.setOnClickListener(this);
Button bindService = (Button)findViewById(R.id.bind_service);
Button unbindService = (Button) findViewById(R.id.unbind_service);
bindService.setOnClickListener(this);
unbindService.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()){
case R.id.start_Service:
Intent startIntent = new Intent(this,MyService.this);
startService(startIntent);
break;
case R.id.stop_Service:
Intent stopIntent = new Intent(this,MyService.this);
stopService(stopIntent);
break;
case R.id.bind_service:
Intent bindIntent = new Intent(this,MyService.class);
//绑定服务
bindService(bindIntent,connection,BIND_AUTO_CREATE);
break;
case R.id.unbind_service:
unbindService(connection);
break;
default:
break;
}
}
}
onCreate 方法和 onStartCommand 有什么区别呢?其实 onCreate 方法只在 service 第一次启动时调用,之后多次启动服务只会调用 onStartCommand
bindService 浅谈
给一张调用流程图,其实底层用的还是 Binder 机制来实现的,内容较多这里就不展开分析了,推荐一个 blog ,对 framework 调用流程分析的已经挺详细了– Service 进阶
IntentService
在 service 中处理耗时操作可能会导致 app 无响应,所以在 service 中必须采用多线程技术,在执行完 service 操作后,咱们不能让 service 一直调用吧?所以需要显式调用 stopService 或者 stopSelf,Android 为了更方便实现多线程的管理,又实现了 IntentService ,耗时的服务处理操作放在 onHandleIntent 函数中进行就可以了,相比之前自己实现多线程,显然是方便了很多。