android中服务的使用 与 Activity和Service的通讯

来源:互联网 发布:俄勒冈州立大学 知乎 编辑:程序博客网 时间:2024/05/18 00:26

转载至: http://blog.csdn.net/xiaanming/article/details/9750689

服务的特点: 不需要依赖于UI界面,可以长时间的执行某项任务.
服务的特性:
1.Service本身都是运行在其所在进程的主线程(如果Service与Clinet同属于一个进程,则是运行于UI线程),但Service一般都是需要进行”长期“操作,所以经常写法是在自定义Service中处理”长期“操作时需要新建线程,以免阻塞UI线程或导致ANR;
2
Service一旦创建,需要停止时都需要显示调用相应的方法(Started Service需要调用stopService(..)或Service本身调用stopSelf(..), Bound Service需要调用unbindService(..)),否则对于Started Service将处于一直运行状态,对于Bound Service,当Client生命周期结束时也将因此问题。也就是说,Service执行完毕后,必须人为的去停止它。

自定义类继承:Service.
然后在功能清单文件中注册.

服务的启动方式:    启动式服务:    以这种方式开启的服务,生命周期与开启的组件的生命周期独立,一旦开启,将长期的在内存在驻留来执行任务,只要给足合适的资源.    生命周期函数:      OnCreate()  当服务第一次被启动时调用      OnStartCommand() 每次调用服务,都会调用该方法      Ondestory()服务销毁之时被调用. 开启服务的代码:
 startServiceBtn.setOnClickListener(new View.OnClickListener() {           @Override         public void onClick(View v) {             serviceIntent = new Intent(MainActivity.this, MyService.class);             startService(serviceIntent);         }     });     stopServideBtn.setOnClickListener(new View.OnClickListener() {         @Override         public void onClick(View v) {             stopService(serviceIntent);         }     });
Service实例一次永远只存在一个,而不管Client是否是相同的组件,也不管Client是否处于相同的进程中。所以,可以在一个组件中开启服务,然后在另外的组件中结束服务.以启动式开启的服务,可以多次被销毁,而不会出错.服务的开启方式还有另外的形式,那就是绑定的方式:以这样的方式开启的服务,将会调用服务中的方法:     Oncreate() 当第一次开启时调用的方法     OnBinde() 服务被绑定时被调用的方法     OnUnBinde() 服务解除绑定时被调用的方法     onRebind() 当OnUnBinde()被调用返回true,服务再次绑定时被调用的方法.   开启服务:        Intent intent=new Intent();        intent.setClass(this, MyService.class);        this.bindService(intent, conn, Context.BIND_AUTO_CREATE);    关闭服务:    Intent intent=new Intent();    intent.setClass(this, MyService.class);    this.unbindService(conn);   绑定时服务有几个特点:   1 生命周期与开启的组件相关,如果开启服务的组件被回收,那么该服务也会被回收  在四大基本组件中,需要注意的的是BroadcastReceiver不能作为Bound Service的Client,因为BroadcastReceiver的生命周期很短,当执行完onReceive(..)回调时,BroadcastReceiver生命周期完结。而Bound Service又与Client本身的生命周期相关,因此,Android中不允许BroadcastReceiver去bindService(..),当有此类需求时,可以考虑通过startService(..)替代   2 在调用的组件中,可以调用服务中的方法3 绑定的服务,可以解除一次绑定,如果多次解除绑定,会报异常,因此,我们需要在解除绑定的代码中,进行判断: 设置标记标量来记录:     // ServiceConnection 中的代码    public void onServiceConnected(ComponentName name, IBinder service) {            //说明绑定成功            if(service!=null){                isBind=true;            }            MyBinder  mybinder=(MyBinder)service;            myservice=mybinder.getInstance();            int random=myservice.getRandom();            Log.v("tag","random:"+random);        }    //解除绑定    public void stop(View view){        if(isBind){            Intent intent=new Intent();            intent.setClass(this, MyService.class);            this.unbindService(conn);            isBind=false;        }    }    //Activity 的销毁方法    protected void onDestroy() {        // TODO Auto-generated method stub        super.onDestroy();        stop(null);    }服务与Activity的通讯,绑定式服务.1.自定义Service继承基类Service,并重写onBind(Intent intent)方法,此方法中需要返回具体的Binder对象;2.Client通过实现ServiceConnection接口来自定义ServiceConnection,并通过bindService (Intent service, ServiceConnection sc, int flags)方法将Service绑定到此Client上;3.自定义的ServiceConnection中实现onServiceConnected(ComponentName name, IBinder binder)方法,获取Service端Binder实例;4.通过获取的Binder实例进行Service端其他公共方法的调用,以完成Client-Service通信;5.当Client在恰当的生命周期(如onDestroy等)时,此时需要解绑之前已经绑定的Service,通过调用函数unbindService(ServiceConnection sc)。服务与Activity之间的通讯:在服务中,自定义Binder,在Binder中提供获取服务实例的方法.    public class MyBinder extends Binder{        //提供获取当前服务实例的方法        public MyService getService(){            return MyService.this;        }    }    @Override    public IBinder onBind(Intent intent) {        // TODO Auto-generated method stub        return new MyBinder();    }在MainActivity中,在绑定服务的第二个参数对象中获取服务的实例:    private ServiceConnection conn=new ServiceConnection() {        @Override        public void onServiceDisconnected(ComponentName name) {            // TODO Auto-generated method stub        }        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            // TODO Auto-generated method stub            //返回MsgService实例            MyBinder binder=(MyBinder)service;            myService = (binder).getService();                  }            });        }    };在服务中进行接口的回调,将变化的结果,通知到主布局中的控件.      /*     * 模拟下载任务     */    public void downLoad(){        new Thread(new Runnable() {            @Override            public void run() {                while(progress<MAX_PROGRESS){                    progress+=5;                    if(listener!=null){                        listener.OnProgress(progress);                    }                    SystemClock.sleep(500);                }            }        }).start();    }在主布局中获取服务,注册接口:     myService.setOnProgressListener(new OnProgressListener() {                @Override                public void OnProgress(int progress) {                    // TODO Auto-generated method stub                    progressbar.setProgress(progress);                }            });当然,对于Activity与服务之间的通信,也可以使用广播的方式.当然,组件之间的通信当然还可以使用广播了在Activity中,自定义局部类的广播,然后动态的注册广播.在服务中发送广播,在广播中控制ui信息更新到Activity中.总结:   1   在我们定义的服务中自定义Bindler对象,然后Activity在绑定服务的时候,在回调的接口中,获取到我们自               定义的Bindler对象的实例,进而获取到服务对象.  采用接口回调的方式,服务注册接口回调,来将我们的进度实时的更新到Activity界面上.   2  在我们的Activity中注册广播,用来更新UI.然后在我们的服务中,当进度发生改变的时候,发送广播来更新UI   操作.不同进程间服务的通讯可以采用信使与AIDL的方式.6.IntentServiceIntentService是系统提供给我们的一个已经继承自Service类的特殊类,IntentService特殊性是相对于Service本身的特性而言的:1.默认直接实现了onBind(..)方法,直接返回null,并定义了抽象方法onHandlerIntent(..),用户自定义子类时,需要实现此方法;2.onHandlerIntent(..)主要就是用来处于相应的”长期“任务的,并且已经自动在新的线程中,用户无语自定义新线程;3.当”长期“任务执行完毕后(也就是onHandlerIntent(..)执行完毕后),此IntentService将自动结束,无需人为调用方法使其结束;4.IntentService处于任务时,也是按照队列的方式一个个去处理,而非真正意义上的多线程并发方式。下面是一个基本的继承自IntentService的自定义Service:

public class MyIntentService extends IntentService {

public static final String TAG = "MyIntentService";public MyIntentService() {    super(TAG);}public MyIntentService(String name) {    super(name);}@Overrideprotected void onHandleIntent(Intent intent) {    Log.w(TAG, "in onHandleIntent");    Log.w(TAG, "thread name:" + Thread.currentThread().getName());}

“`

0 0