浅谈Android四大组件之Service

一:Service简介java

Android开发中,当须要建立在后台运行的程序的时候,就要使用到Service。android

1:Service(服务)是一个没有用户界面的在后台运行执行耗时操做的应用组件。其余应用组件可以启动Service,而且当用户切换到另外的应用场景,Service将持续在后台运行。另外,一个组件可以绑定到一个service与之交互(IPC机制),例如,一个service可能会处理网络操做,播放音乐,操做文件I/O或者与内容提供者(content provider)交互,全部这些活动都是在后台进行。网络

 

2:Service有两种状态,“启动的”和“绑定:app

经过startService()启动的服务处于“启动的”状态,一旦启动,service就在后台运行,即便启动它的应用组件已经被销毁了。一般started状态的service执行单任务而且不返回任何结果给启动者。好比当下载或上传一个文件,当这项操做完成时,service应该中止它自己。ide

 

还有一种“绑定”状态的service,经过调用bindService()来启动,一个绑定的service提供一个容许组件与service交互的接口,能够发送请求、获取返回结果,还能够经过夸进程通讯来交互(IPC)。绑定的service只有当应用组件绑定后才能运行,多个组件能够绑定一个service,当调用unbind()方法时,这个service就会被销毁了。布局

 

3:serviceactivity同样都存在与当前进程的主线程中,因此,一些阻塞UI的操做,好比耗时操做不能放在service里进行,好比另外开启一个线程来处理诸如网络请求的耗时操做。若是在service里进行一些耗CPU和耗时操做,可能会引起ANR警告,这时应用会弹出是强制关闭仍是等待的对话框。因此,对service的理解就是和activity平级的,只不过是看不见的,在后台运行的一个组件,这也是为何和activity同被说为Android的基本组件。this

 

二:Service的生命周期spa

Android Service生命周期与Activity生命周期是类似的,可是也存在一些细节上也存在着重要的不一样:线程

onCreateonStart是不一样的3d

经过从客户端调用Context.startService(Intent)方法咱们能够启动一个服务。若是这个服务尚未运行,Android将启动它而且在onCreate方法以后调用它的onStart方法。若是这个服务已经在运行,那么它的onStart方法将被新的Intent再次调用。因此对于单个运行的Service它的onStart方法被反复调用是彻底可能的而且是很正常的。

onResumeonPause以及onStop是不须要的

回调一个服务一般是没有用户界面的,因此咱们也就不须要onPauseonResume或者onStop方法了。不管什么时候一个运行中的Service它老是在后台运行。

onBind

若是一个客户端须要持久的链接到一个服务,那么他能够调用Context.bindService方法。若是这个服务没有运行方法将经过调用onCreate方法去建立这个服务但并不调用onStart方法来启动它。相反,onBind方法将被客户端的Intent调用,而且它返回一个IBind对象以便客户端稍后能够调用这个服务。同一服务被客户端同时启动和绑定是很正常的。

onDestroy

Activity同样,当一个服务被结束是onDestroy方法将会被调用。当没有客户端启动或绑定到一个服务时Android将终结这个服务。与不少Activity时的状况同样,当内存很低的时候Android也可能会终结一个服务。若是这种状况发生,Android也可能在内存够用的时候尝试启动被终止的服务,因此你的服务必须为重启持久保存信息,而且最好在onStart方法内来作。

 

三.Service的启动方式

Service的启动方式有以下2种

CstartService()和bindService(),这两种方式对Service生命周期的影响是不一样的

startservice是由其余组件调用startService()方法启动的,这致使服务的onStartCommand()方法被调用,当服务是started状态时,其生命周期与启动它的组件无关,而且能够在后台无限期运行,即便启动服务的组件已经被销毁。所以,服务须要在完成任务后调用stopself()方法中止,或者有其余组件调用stopService()方法中止。

使用bindService()方法启用服务,调用者与服务绑定在了一块儿,调用者一旦退出,服务也就终止,大有‘不求同生,但求同死’的特色

Android应用中每一个Service都必需要在AndroidMainifest.Xml配置文件中声明。

 四:2种启动方式的具体例子

 

startService()方式的生命周期: 
启动时,startService –> onCreate() –> onStart()

中止时,stopService –> onDestroy()

 

若是调用者直接退出而没有中止Service,则Service 会一直在后台运行
 
Context.startService()方法启动服务,在服务未被建立时,系统会先调用服务的onCreate()方法,接着调用onStart()方法。若是调用startService()方法前服务已经被建立,屡次调用startService()方法并不会致使屡次建立服务,但会致使屡次调用onStart()方法。采用startService()方法启动的服务,只能调用Context.stopService()方法结束服务,服务结束时会调用onDestroy()方法。

 

startService()方式启动 Service的方法:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    > 
    <Button 
        android:id="@+id/startBtn" 
        android:layout_width="match_parent" 
        android:layout_height="wrap_content" 
        android:text="启动 Service" 
        /> 
    <Button 
        android:id="@+id/stopBtn" 
        android:layout_width="match_parent" 
        android:layout_height="wrap_content" 
        android:text="中止 Service" 
        /> 
</LinearLayout> 

MainActivity.java

package com.android.service.activity;  
 
import android.app.Activity;  
import android.content.Intent;  
import android.os.Bundle;  
import android.view.View;  
import android.view.View.OnClickListener;  
import android.widget.Button;  
 
public class MainActivity extends Activity  
{  
    private Button startBtn;  
    private Button stopBtn;  
    @Override 
    public void onCreate(Bundle savedInstanceState)  
    {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.main);  
        startBtn = (Button) findViewById(R.id.startBtn);  
        stopBtn = (Button) findViewById(R.id.stopBtn);  
        //添加监听器  
        startBtn.setOnClickListener(listener);  
        stopBtn.setOnClickListener(listener);  
    }  
      
    //启动监听器  
    private OnClickListener listener=new OnClickListener()  
    {         
        @Override 
        public void onClick(View v)  
        {  
            Intent intent=new Intent(MainActivity.this, ServiceDemo.class);  
            switch (v.getId())  
            {  
            case R.id.startBtn:  
                startService(intent);  
                break;  
            case R.id.stopBtn:  
                stopService(intent);  
                break;  
            default:  
                break;  
            }             
        }  
    };  
} 

新建ServiceDemo类,ServiceDemo.java以下

package com.android.service.activity;  
 
import android.app.Service;  
import android.content.Intent;  
import android.os.IBinder;  
import android.util.Log;  
 
public class ServiceDemo extends Service  
{  
    private static final String TAG="Test";  
      
    @Override 
    //Service时被调用  
    public void onCreate()  
    {  
        Log.i(TAG, "Service onCreate--->");  
        super.onCreate();  
    }  
 
    @Override 
    //当调用者使用startService()方法启动Service时,该方法被调用  
    public void onStart(Intent intent, int startId)  
    {  
        Log.i(TAG, "Service onStart--->");  
        super.onStart(intent, startId);  
    }  
 
    @Override 
    //当Service不在使用时调用  
    public void onDestroy()  
    {  
        Log.i(TAG, "Service onDestroy--->");  
        super.onDestroy();  
    }  
 
    @Override 
    //当使用startService()方法启动Service时,方法体内只需写return null  
    public IBinder onBind(Intent intent)  
    {  
        return null;  
    }  
}  

在AndroidManifest.xml文件中添加16~21行的声明

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
      package="com.android.service.activity" 
      android:versionCode="1" 
      android:versionName="1.0"> 
    <uses-sdk android:minSdkVersion="10" /> 
 
    <application android:icon="@drawable/icon" android:label="@string/app_name"> 
        <activity android:name=".MainActivity" 
                  android:label="@string/app_name"> 
            <intent-filter> 
                <action android:name="android.intent.action.MAIN" /> 
                <category android:name="android.intent.category.LAUNCHER" /> 
            </intent-filter> 
        </activity> 
    <service android:name=".ServiceDemo" >    
             <intent-filter> 
                <action android:name="android.intent.action.MAIN" /> 
                <category android:name="android.intent.category.LAUNCHER" /> 
            </intent-filter> 
    </service>    
    </application> 
</manifest> 

效果以下:

当点击按钮时,前后执行了Service中onCreate()->onStart()这两个方法,LogCat显示以下:

当点击 按钮时,Service则执行了onDestroy()方法,LogCat显示以下:

 

退出后,进入Settings(设置)->Applications(应用)->Running Services(正在运行的服务)看一下咱们新启动了的服务,效果图以下:

 

 

 
 
bindService()方式的生命周期: 
绑定时,bindService -> onCreate() –> onBind()
调用者退出了,即解绑定时,Srevice就会unbindService –>onUnbind() –> onDestory()
 
用Context.bindService()方法启动服务,在服务未被建立时,系统会先调用服务的onCreate()方法,接着调用onBind()方法。这个时候调用者和服务绑定在一块儿,调用者退出了,系统就会先调用服务的onUnbind()方法,接着调用onDestroy()方法。若是调用bindService()方法前服务已经被绑定,屡次调用bindService()方法并不会致使屡次建立服务及绑定(也就是说onCreate()和onBind()方法并不会被屡次调用)。若是调用者但愿与正在绑定的服务解除绑定,能够调用unbindService()方法,调用该方法也会致使系统调用服务的onUnbind()-->onDestroy()方法。
 bindService()方式启动 Service的方法:
绑定Service须要三个参数:bindService(intent, conn, Service.BIND_AUTO_CREATE);
第一个:Intent对象
第二个:ServiceConnection对象,建立该对象要实现它的onServiceConnected()和 onServiceDisconnected()来判断链接成功或者是断开链接
第三个:如何建立Service,通常指定绑定的时候自动建立。
例子以下:
main.xml
<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:orientation="vertical" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    > 
    <Button   
        android:text="启动Service"   
        android:id="@+id/startBtn1"   
        android:layout_width="match_parent"   
        android:layout_height="wrap_content" 
        />    
    <Button   
        android:text="中止Service"   
        android:id="@+id/stopBtn2"   
        android:layout_width="match_parent"   
        android:layout_height="wrap_content" 
        />    
    <Button   
        android:text="绑定Service"   
        android:id="@+id/bindBtn3"   
        android:layout_width="match_parent"   
        android:layout_height="wrap_content" 
        /> 
    <Button   
        android:text="解除绑定"   
        android:id="@+id/unbindBtn4"   
        android:layout_width="match_parent"   
        android:layout_height="wrap_content" 
        /> 
</LinearLayout> 

MainActivity.java

package com.android.bindservice.activity;  
 
import android.app.Activity;  
import android.app.Service;  
import android.content.ComponentName;  
import android.content.Intent;  
import android.content.ServiceConnection;  
import android.os.Bundle;  
import android.os.IBinder;  
import android.util.Log;  
import android.view.View;  
import android.view.View.OnClickListener;  
import android.widget.Button;  
 
public class MainActivity extends Activity {  
    // 声明Button  
    private Button startBtn,stopBtn,bindBtn,unbindBtn;  
    @Override 
    public void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        // 设置当前布局视图  
        setContentView(R.layout.main);  
        // 实例化Button  
        startBtn = (Button)findViewById(R.id.startBtn1);  
        stopBtn = (Button)findViewById(R.id.stopBtn2);  
        bindBtn = (Button)findViewById(R.id.bindBtn3);  
        unbindBtn = (Button)findViewById(R.id.unbindBtn4);  
          
        // 添加监听器  
        startBtn.setOnClickListener(startListener);  
        stopBtn.setOnClickListener(stopListener);  
        bindBtn.setOnClickListener(bindListener);  
        unbindBtn.setOnClickListener(unBindListener);  
          
    }  
    // 启动Service监听器  
    private OnClickListener startListener = new OnClickListener() {  
        @Override 
        public void onClick(View v) {  
            // 建立Intent  
            Intent intent = new Intent();  
            // 设置Class属性  
            intent.setClass(MainActivity.this, BindService.class);  
            // 启动该Service  
            startService(intent);  
        }  
    };  
      
    // 中止Service监听器  
    private OnClickListener stopListener = new OnClickListener() {  
        @Override 
        public void onClick(View v) {  
            // 建立Intent  
            Intent intent = new Intent();  
            // 设置Class属性  
            intent.setClass(MainActivity.this, BindService.class);  
            // 启动该Service  
            stopService(intent);  
        }  
    };  
      
   // 链接对象  
   private ServiceConnection conn = new ServiceConnection() {  
        @Override 
        public void onServiceConnected(ComponentName name, IBinder service) {  
            Log.i("Service", "链接成功!");  
        }  
        @Override 
        public void onServiceDisconnected(ComponentName name) {  
            Log.i("Service", "断开链接!");  
        }  
    };  
      
    // 綁定Service监听器  
    private OnClickListener bindListener = new OnClickListener() {  
        @Override 
        public void onClick(View v) {  
            // 建立Intent  
            Intent intent = new Intent();  
            // 设置Class属性  
            intent.setClass(MainActivity.this, BindService.class);  
           
            // 绑定Service  
            bindService(intent, conn, Service.BIND_AUTO_CREATE);  
        }  
    };  
          
    // 解除绑定Service监听器  
    private OnClickListener unBindListener = new OnClickListener() {  
        @Override 
        public void onClick(View v) {  
            // 建立Intent  
            Intent intent = new Intent();  
            // 设置Class属性  
            intent.setClass(MainActivity.this, BindService.class);  
            // 解除绑定Service  
            unbindService(conn);  
        }  
    };    
} 

BindService.java

package com.android.bindservice.activity;  
 
import android.app.Service;  
import android.content.Intent;  
import android.os.IBinder;  
import android.util.Log;  
 
public class BindService extends Service{  
      
    private static final String TAG="Test";  
      
    //返回null  
    public IBinder onBind(Intent intent) {  
        Log.i(TAG, "Service onBind--->");  
        return null;  
    }  
    // Service建立时调用  
    public void onCreate() {  
        Log.i(TAG, "Service onCreate--->");  
    }  
    // 当客户端调用startService()方法启动Service时,该方法被调用  
    public void onStart(Intent intent, int startId) {  
        Log.i(TAG, "Service onStart--->");  
    }  
    // 当Service再也不使用时调用  
    public void onDestroy() {  
        Log.i(TAG, "Service onDestroy--->");  
    }  
    // 当解除绑定时调用  
    public boolean onUnbind(Intent intent) {    
        Log.i(TAG, "Service onUnbind--->");    
        return super.onUnbind(intent);    
    }    
}  

 

在AndroidManifest.xml文件中添加16~21行的声明

<?xml version="1.0" encoding="utf-8"?> 
<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
      package="com.android.bindservice.activity" 
      android:versionCode="1" 
      android:versionName="1.0"> 
    <uses-sdk android:minSdkVersion="10" /> 
 
    <application android:icon="@drawable/icon" android:label="@string/app_name"> 
        <activity android:name=".MainActivity" 
                  android:label="@string/app_name"> 
            <intent-filter> 
                <action android:name="android.intent.action.MAIN" /> 
                <category android:name="android.intent.category.LAUNCHER" /> 
            </intent-filter> 
        </activity> 
        <service android:name=".BindService" >    
             <intent-filter> 
                <action android:name="android.intent.action.MAIN" /> 
                <category android:name="android.intent.category.LAUNCHER" /> 
            </intent-filter> 
    </service> 
    </application> 
</manifest> 

效果以下:

当点击按钮时,前后执行了Service中onCreate()->onStart()这两个方法,LogCat显示以下:

当点击按钮,则Service执行了onUnbind()方法,LogCat显示以下:

 

当点击按钮,则Service执行了onUnbind()方法,LogCat显示以下:

相关文章
相关标签/搜索