一直以为stopService和unbindService可以销毁service运行的耗时操作,但是发现执行前面两个方法只是执行了ondestory方法,运行的耗时操作仍然在后台运行,代码如下所示:
public class StartServiceActivity extends BaseActivity {
private Button startButton;
private Button stopButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
protected void initView() {
setContentView(R.layout.activity_start_service);
startButton = f(R.id.startButton);
stopButton = f(R.id.stopButton);
startButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
startService(new Intent(StartServiceActivity.this, MyService.class));
}
});
stopButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
stopService(new Intent(StartServiceActivity.this, MyService.class));
}
});
}
@Override
protected void loadData() {
}
}
service代码如下:
public class MyService extends Service {
private static final String TAG = "MyService";
private static final int MAX = 100;
private int currentProsess;
private Handler handler = new Handler();
private Runnable runnable = new Runnable() {
@Override
public void run() {
currentProsess++;
Log.d(TAG, "run() called======" + currentProsess);
handler.postDelayed(runnable, 1000);
}
};
public MyService() {
}
@Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate() called");
handler.post(runnable);
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand() called with: intent = [" + intent + "], flags = [" + flags + "], startId = [" + startId + "]");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
//发现使用stopSelf();也并不能关闭耗时操作
// stopSelf();
//解决办法是在onDestory里面自己手动解决耗时操作
handler.removeCallbacks(runnable);
Log.d(TAG, "onDestroy() called");
}
}
下面是onDestroy()方法中执行stopSelf();的方法,发现耗时操作并未停止运行;
2019-07-27 23:38:28.920 24590-24590/com.example.hasee.water D/MyService: onCreate() called
2019-07-27 23:38:28.921 24590-24590/com.example.hasee.water D/MyService: onStartCommand() called with: intent = [Intent { cmp=com.example.hasee.water/.service.MyService }], flags = [0], startId = [1]
2019-07-27 23:38:28.922 24590-24590/com.example.hasee.water D/MyService: run() called======1
2019-07-27 23:38:29.923 24590-24590/com.example.hasee.water D/MyService: run() called======2
2019-07-27 23:38:30.925 24590-24590/com.example.hasee.water D/MyService: run() called======3
2019-07-27 23:38:31.929 24590-24590/com.example.hasee.water D/MyService: run() called======4
2019-07-27 23:38:32.838 24590-24590/com.example.hasee.water D/MyService: onDestroy() called
2019-07-27 23:38:32.930 24590-24590/com.example.hasee.water D/MyService: run() called======5
2019-07-27 23:38:33.933 24590-24590/com.example.hasee.water D/MyService: run() called======6
2019-07-27 23:38:34.934 24590-24590/com.example.hasee.water D/MyService: run() called======7
下面是onDestroy()方法里执行handler.removeCallbacks(runnable);此时耗时操作停止运行,所以我们想终止服务里运行的耗时操作,我们应该手动去移除
2019-07-27 23:38:28.920 24590-24590/com.example.hasee.water D/MyService: onCreate() called
2019-07-27 23:38:28.921 24590-24590/com.example.hasee.water D/MyService: onStartCommand() called with: intent = [Intent { cmp=com.example.hasee.water/.service.MyService }], flags = [0], startId = [1]
2019-07-27 23:38:28.922 24590-24590/com.example.hasee.water D/MyService: run() called======1
2019-07-27 23:38:29.923 24590-24590/com.example.hasee.water D/MyService: run() called======2
2019-07-27 23:38:30.925 24590-24590/com.example.hasee.water D/MyService: run() called======3
2019-07-27 23:38:31.929 24590-24590/com.example.hasee.water D/MyService: run() called======4
2019-07-27 23:38:32.838 24590-24590/com.example.hasee.water D/MyService: onDestroy() called
关于activity和service交互的问题:
我们不能使用startService来启动,因为activity拿不到启动的service,只能通过bindService来启动,因为service通过
onBind方法可以返回binder,而我们在activity中可以通过ServiceConnection的onServiceConnected拿到binder,通过binder来操作service中的方法,这样他们就关联上了:
activity中的代码:
public class DownLoadActivity extends BaseActivity {
private static final String TAG = "DownLoadActivity";
private static final String TAG1 = "DownLoadService";
private Button downLoadButton,unBindServicebutton;
private TextView downLoadProgressTextView;
private DownLoadService downLoadService;
private int currentProgress = 0;
private DownLoadService.DownLoadBinder downLoadBinder;
private boolean haveBindService;
ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
downLoadBinder = (DownLoadService.DownLoadBinder) iBinder;
Log.d(TAG, "onServiceConnected() called with: componentName = [" + componentName + "], iBinder = [" + iBinder + "]");
if(null!=downLoadBinder){
downLoadBinder.startDownLoad();
}else{
Log.d(TAG, "onServiceConnected: 未获取到service");
}
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
Log.d(TAG1, "DownLoadService------onServiceDisconnected: 断开了连接");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
protected void initView() {
setContentView(R.layout.activity_down_load);
downLoadButton = f(R.id.downLoadButton);
unBindServicebutton=f(R.id.unBindServicebutton);
downLoadProgressTextView = f(R.id.downLoadProgressTextView);
final Intent intent = new Intent(this,DownLoadService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
intent.setPackage(getPackageName());
bindService(intent, serviceConnection, BIND_AUTO_CREATE);
} else {
bindService(intent, serviceConnection, BIND_AUTO_CREATE);
}
haveBindService=true;
downLoadButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (null != downLoadBinder) {
downLoadBinder.startDownLoad();
downLoadBinder.setDomnLoadListener(new DownLoadService.DownLoadListener() {
@Override
public void prosess(final int prosess) {
runOnUiThread(new Runnable() {
@Override
public void run() {
downLoadProgressTextView.setText("下载进度=" + prosess + "%");
}
});
}
});
}
}
});
unBindServicebutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(haveBindService){
unbindService(serviceConnection);
haveBindService=false;
}
}
});
}
@Override
protected void loadData() {
}
}
service中的代码:
public class DownLoadService extends Service {
private static final String TAG = "DownLoadService";
private static final int TOTAL_PROGRESS=100;
private int currentProGress=0;
public DownLoadListener mDownLoadListener;
private DownLoadBinder downLoadBinder=new DownLoadBinder();
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy() called-----服务被关闭");
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return downLoadBinder;
}
public void downLoad(){
new Thread(new Runnable() {
@Override
public void run() {
while (currentProGress<TOTAL_PROGRESS){
currentProGress+=1;
try {
Thread.sleep(1000);
if(null!=mDownLoadListener){
mDownLoadListener.prosess(currentProGress);
Log.d(TAG, "run() called----当前下载进度="+currentProGress);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
stopSelf();
}
public interface DownLoadListener{
void prosess(int prosess);
}
public class DownLoadBinder extends Binder{
public void startDownLoad(){
Log.d(TAG, "startDownLoad: 开始下载.......");
downLoad();
}
public int getProgress(){
return currentProGress;
}
public void setDomnLoadListener(DownLoadListener domnLoadListener){
mDownLoadListener=domnLoadListener;
}
}
}当然之里面在ondestory里面没有对线程进行移除,所以调用ondestory方法以后线程仍在后台继续运行,直到任务完成。注意:startService和bindService都是可以启动service,但是service的生命周期会不一样。