Service创建有两种方法:  startService或者bindService



服务不能自己运行,需要通过调用Context.startService()或Context.bindService()方法启动服务。这两个方法都可以启动Service,但是它们的使用场合有所不同。使用startService()方法启用服务,调用者与服务之间没有关连,即使调用者退出了,服务仍然运行。使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止,大有“不求同时生,必须同时死”的特点。




如果打算采用 Context.startService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onStart()方法。如果调用startService()方法前服务已经被创建, 多次调用startService()方法并不会导致多次创建服务, 但会导致多次调用onStart()方法。采用startService()方法启动的服务,只能调用Context.stopService()方法结束服务,服务结束时会调用onDestroy()方法。




如果打算采用 Context.bindService()方法启动服务,在服务未被创建时,系统会先调用服务的onCreate()方法,接着调用onBind()方法。这个时候调用者和服务绑定在一起,调用者退出了,系统就会先调用服务的onUnbind()方法,接着调用onDestroy()方法。如果调用bindService()方法前服务已经被绑定,多次调用bindService()方法并不会导致多次创建服务及绑定(也就是说onCreate()和onBind()方法并不会被多次调用)。如果调用者希望与正在绑定的服务解除绑定,可以调用unbindService()方法,调用该方法也会导致系统调用服务的onUnbind()-->onDestroy()方法。



 



service中可以下载,但是你要保证在系统的规定crash时间内完成,否则,你就会阻塞UI.



为什么播放不会阻塞,应为MediaPlayer使用了Handler + Looper 去更新UI.

public MediaPlayer() { 
     
         Looper looper; 
     
         if ((looper = Looper.myLooper()) != null) { 
     
             mEventHandler = new EventHandler(this, looper); 
     
         } else if ((looper = Looper.getMainLooper()) != null) { 
     
             mEventHandler = new EventHandler(this, looper); 
     
         } else { 
     
             mEventHandler = null; 
     
         } 
     
         /* Native setup requires a weak reference to our object. 
     
          * It's easier to create it here than in C++. 
     
          */ 
     
         native_setup(new WeakReference<MediaPlayer>(this)); 
     
     }



如何在Service里维护多线程处理操作呢?(如:多线程下载)



1.首先要维护好一个任务队列



在Android开发当中,很多情况都会遇到多线程的时候。需要开启一条线程完成单独的任务。当需要对子线程进行生命控制并且要与主线程进行交互时。
HandlerThread 与Future就是一种很好的机制。

Looper和HandlerThread 。 Android提供的线程都带有一个Looper。 looper可以帮助线程维护一个消息队列。 Android使用Looper机制才能接受消息和处理
计划任务。  HandlerThread中封装了Looper对象。可以通过getLooper方法获取一个Looper对象。
 
不管是主线程还是子线程,只要有Looper线程,其他的线程就可以向这个线程的消息队列中发送消息和计划任务,然后做相应的处理。



 



2.每个任务都是一个线程在处理,用Callable实现返回线程任务执行状态



Callable/Future Callable接口类似于Runnable接口。实现Callable接口和实现Runnale接口的类都是可以被其他线程执行的任务。

Callable和Runnable的区别如下:

  Callable定义的方法是call,而Runnable定义的方法是run。

  Callable的call方法可以有返回值,而Runnable的run方法不能有返回值。

  Callable的call方法可抛出异常,而Runnable的run方法不能抛出异常。

Future 表示异步任务的结果。它提供了检查任务是否完成的方法,以等待任务完成。并得到任务执行结果。通过Future可以对任务的生命周期进行控制。取消任务,判断任务是否执行完成。获取任务执行完成的结果。
其实Future只是一个接口,在java6中,提供了一个FutureTask对Future进行封装。在Android中,在某些情景下,使用FutureTask并不是很方便。我们可以单独的重新设计Future和FutureTask。

Future.java: 
     
   
     public interface Future<T>{ 
     
   
       
       
      public void cancel();  
      // 取消任务 
     

   
       
       
      public boolean isCancelled();  
      // 判断任务是否已被取消 
     

   
       
       
      public boolean isDone(); // 判断任务是否已完成 
     

   
       
       
       
      public T get(); // 获取任务完成的结果 
     

   
       
       
      public void waitDone(); // 等待完成 
     
   
     }



创建一个任务完成时的事件监听类。

FutureListener.java 
     

   
       
       
      public interface FutureListener<T>{ 
     
   
       
       
        
       
       
      public void onFutureDone(Future<T> future); 
     
   
       
       
      } 
     


 FutureTask.java 
     

   
     public class FutureTask<T> implements Runnable,Future<T>{ 
     
   
       
       
      private Callable<T> mCallable ; 
     
   
       
       
      private FutureListener<T> mListener ; 
     
   
       
       
      private boolean mIsDone ; 
     
   
       
       
      private volatile boolean mIsCancelled ; 
     
   
       
       
      private T mResult ; 
     

   
       
       
      public FutureTask(Callable<T> callable,FutureListener<T> listener){ 
     
   
       
       
        
       
       
      this.mCallable = callable ; 
     
   
       
       
        
       
       
      this.mListener = listener ; 
     
   
       
       
      } 
     
   
       
       
      public FutureTask(Callable<T> callable){ 
     
   
       
       
        
       
       
      this(callable,null); 
     
   
       
       
      }  
       
       
     

   
       
       
      public void cancel(){ 
     
   
       
       
        
       
       
      mIsCancelled = true ; 
     
   
       
       
      } 
     
   
       
       
     
   
       
       
      public boolean isCancelled(){ 
     
   
       
       
        
       
       
      return mIsCancelled ; 
     
   
       
       
      } 
     
   
       
       
     
   
       
       
      public synchronized boolean isDone(){ 
     
   
       
       
        
       
       
      return mIsDone ; 
     
   
       
       
      } 
     

   
       
       
      public synchronized T get(){ 
     
   
       
       
        
       
       
      while(!mIsDone){ 
     
   
       
       
        
       
       
        
       
       
      try{ 
     
   
       
       
        
       
       
        
       
       
        
       
       
      wait(); 
     
   
       
       
        
       
       
        
       
       
      }catch(Exception e){} 
     
   
       
       
        
       
       
        
       
       
        
       
       
        
       
       
     
   
       
       
        
       
       
      } 
     
   
       
       
        
       
       
      return mResult ; 
     
   
       
       
      } 
     

   
       
       
      public void waitDone(){ 
     
   
       
       
        
       
       
      get(); 
     
   
       
       
      } 
     

   
       
       
      public void run(){ 
     
   
       
       
        
       
       
      T  
      t = null ; 
     
   
       
       
        
       
       
      if(!mIsCancelled){ 
     
   
       
       
        
       
       
        
       
       
      try{ 
     
   
       
       
        
       
       
        
       
       
        
       
       
      t = mCallable.call(); 
     
   
       
       
        
       
       
        
       
       
      }catch(Exception e){} 
     
   
       
       
        
       
       
      } 
     

   
       
       
        
       
       
      synchronized(this){ 
     
   
       
       
        
       
       
        
       
       
      mResult = t ; 
     
   
       
       
        
       
       
        
       
       
      mIsDone = ture ; 
     
   
       
       
        
       
       
        
       
       
      if(mListener != null ) 
     
   
       
       
        
       
       
        
       
       
        
       
       
      mListener.onFutureDone(this); 
     
   
       
       
        
       
       
        
       
       
      notifyAll(); 
     
   
       
       
        
       
       
      } 
     
   
       
       
      } 
     
   
     }

3.Future 的调用:
      我们需要将我们的任务线程消息发送到主线程(UI)的Looper中,首先需要获取Looper。
主线程与子线程之间的消息交互通过Handler 完成。需要创建一个Handler对象。

HandlerThread mThread = new HandlerThread("DataThread",Process.THREAD_PRIORITY_BACKGROUND); 
     
 mThread.start(); 
     

 Handler mHandler = new Handler(mThread.getLooper); 
     

 FutureTask<Integer> mTask = new FutureTask<Integer>(new MyCallable()); 
     
 mHandler.post(mTask); 
     
 int result = mTask.get(); 
     


 class MyCallable implements Callable<Integer>{ 
     
   
       
       
      public Integer call() throws Exception{ 
     
   
       
       
        
       
       
      // do what ... 
     
   
       
       
        
       
       
      return 2 ; 
     
   
       
       
      } 
     
 }