1.继承Service
2.实现service的两种方式(startService,bindservice)
在通过bind方式启动service之后,再通过start方式启动之时,只会调用onStartCommand而不会onCreate
2.1 startService启动service
注:一旦通过startService,可在同一应用中再次执行startService操作,而在新的启动中,不在执行onCreate,而是执行startCommand和onstart,而且在一个应用中,多次startService,关闭它只需要一次。
service代码
public class MyService extends Service {
private static final String TAG = "MyService";
int i = 0;
@Override
public void onCreate() {
super.onCreate();
Toast.makeText(this, "开启服务" + i ,2000).show();
Log.d(TAG , "onCreate : " + i);
i++;
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Log.d(TAG , "onStart");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG , "onStartCommand");
Toast.makeText(this, intent.getStringExtra("from"), 2000).show();
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.d(TAG , "onDestroy");
Toast.makeText(this, "关闭服务" ,2000).show();
super.onDestroy();
// stopSelf();
}
}
通过startService方法调用
Intent intent = null;//new Intent();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intent = new Intent(this, MyService.class);
intent.putExtra("from","mian1");
findViewById(R.id.button3).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startService(intent);
}
});
findViewById(R.id.button4).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
stopService(intent);
}
});
findViewById(R.id.button9).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// stopService(intent);
Intent intent = new Intent(MainActivity.this, Main2Activity.class);
startActivity(intent);
}
});
}
2.2 bindService启动(有点小麻烦)
可以通过代理机制在activity中调用service中的方法,奇怪的问题是:在unbind–》ondestroy之后,activity调用通过“吃饭”和“打小胖子”方法,toast依然可以show
1.service实现
package com.lunch.wushengqi.mymedio;
import android.app.Service;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.util.Log;
import android.widget.Toast;
public class MyService extends Service {
private static final String TAG = "MyService";
int i = 0;
@Override
public void onCreate() {
super.onCreate();
Toast.makeText(this, "开启服务" + i ,2000).show();
Log.d(TAG , "onCreate : " + i);
i++;
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
// throw new UnsupportedOperationException("Not yet implemented");
Log.d(TAG , "onBind");
//返回的binder对象在activity中被实现,binder中存放的是service的对象
return new MyBinder(this);
}
@Override
public boolean onUnbind(Intent intent) {
Log.d(TAG , "onUnbind");
return super.onUnbind(intent);
}
@Override
public void onRebind(Intent intent) {
Log.d(TAG , "onRebind");
super.onRebind(intent);
}
@Override
public void onDestroy() {
Log.d(TAG , "onDestroy");
Toast.makeText(this, "关闭服务" ,2000).show();
super.onDestroy();
// stopSelf();
}
public void eat(){
toast("吃饭");
}
public void da(){
toast("打小胖子");
}
public void toast(String text){
Toast.makeText(this, text ,2000).show();
}
}
2.binder的实现
package com.lunch.wushengqi.mymedio;
import android.os.Binder;
/**
* Created by Administrator on 2016/5/28.
*/
public class MyBinder extends Binder {
private MyService myService;
public MyBinder(MyService myService){
this.myService = myService;
}
public MyService getServices(){
return myService;
}
}
3.Activity中实现binderservice
package com.lunch.wushengqi.mymedio;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.IBinder;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
public class Main2Activity extends AppCompatActivity {
Intent bindIntent = null;
private MyService myService = null;
ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//通过IBinder代理,获取service服务中public IBinder onBind(Intent intent)方法返回的自定义binder对象,并向下转型获取其中的内容
myService = ((MyBinder)service).getServices();
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
findViewById(R.id.button7).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// startIntent = new Intent(Main2Activity.this, MyService.class);
bindIntent = new Intent(Main2Activity.this, MyService.class);
bindService(bindIntent, connection, Context.BIND_AUTO_CREATE);
}
});
findViewById(R.id.button8).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// startIntent = new Intent(Main2Activity.this, MyService.class);
unbindService(connection);
}
});
findViewById(R.id.eat).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
myService.eat();
}
});
findViewById(R.id.da).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
myService.da();
}
});
}
}
IntentService(按start顺序执行)(记得看源码)
启动方式和startService一样,但是执行顺序和start顺序保持一致。其特点在于,在service中默认开启有序的子线程(一个service一个子线程),执行顺序和start顺序一致,我们只需要在protected void onHandleIntent(Intent intent) 方法中实现我们要实现的逻辑即可。
三、 拓展知识(进程和生命周期):
Android操作系统尝试尽可能长时间保持应用的进程,但当可用内存很低时要移走一部分进程。哪些程序可以运行,哪些要被销毁?答案是:重要级别低的进程可能被淘汰。
按照重要性排列,一共可以分成5级:
1、前台运行进程:
用户此时需要处理和显示的进程。符合下列条件任何一个,这个进程就被认为是前台运行进程。
与用户正发生交互;
它控制一个与用户交互的必须的基本的服务;
一个正在调用生命周期回调方法的ervice(如onCreate()、onStar()、onDestroy());
一个正在运行onReceive()方法的广播接收对象。
销毁前台运行进程是系统万不得已的、最后的选择——当内存不够系统继续运行下去时,杀掉一些前台进程来保证能够响应用户的需求。
2、可用进程:
一个可用进程没有任何前台组件,但它仍然可以影响到用户的界面。下面情况发生时,可以称该进程为可用进程。
它是一个非前台的activity,但对用户仍然可用(onPause()方法已经被调用)。例如:前台的activity是一个允许上一个activity可见的对话框。也就是说当前activity中是一个对话框,对话框之外的地方能看到前一个activity的界面。
3、服务进程:
服务进程是一个通过调用startService()方法启动的服务,并且不属于前两种情况。尽管服务进程没有直接被用户看到,但他们确实是用户所关心的,比如后台播放音乐或网络下载数据,所以系统保证他们的运行。
4、后台进程:
一个后台进程就是非当前正在运行的activity(activity的onStop()方法已经被调用),他们不会对用户体验造成直接的影响,当没有足够内存来运行前台可见程序时,他们将会被终止。
通常,后台进程会有很多个在运行,LRU最近使用程序列表来保证经常运行的activity能最后一个被终止。
5、空线程:
一个空线程没有运行任何可用应用程序,保留他们的唯一原因是为了设立一个缓存机制,来加快组件启动的时间。系统经常杀死这些内存来平衡系统的整个系统的资源,进程缓存和基本核心缓存之间的资源。