Android Service中的startService和bindService

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 = 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 ;
      }
}




 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值