Android Service启动方式以及生命周期以及通信总结

           众所周知,Service 是四大天王之一,所以深入了解Service非常重要,Service主要运行在后台,它主要用于在后台处理一些耗时的逻辑,或者去执行某些需要长期运行的任务。必要的时候我们甚至可以在程序退出的情况下,让Service在后台继续保持运行状态。

         怎么启动它呢?有两种方式,一种是startService(intent),开启一个Service,另一种是bindService(intent, conn, BIND_AUTO_CREATE);即是绑定Service;

        下面分别演示一下2种方式,

         1.startService(intent);

         布局写了5个按钮,分别是用来启动Service、停止Service、绑定Service 、解绑Service 、启动到第二activity

     <pre name="code" class="java">public class MainActivity extends Activity {
	private Button startBtn,stopBtn,bindBtn,unBindBtn,nextBtn;
	private final String image_path = "";
	private Intent intent;
	public final static String Tag = "main";
	//private MyBinder binder;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		startBtn = (Button)findViewById(R.id.button1);
		stopBtn =  (Button)findViewById(R.id.button2);
		bindBtn = (Button)findViewById(R.id.button3);
		unBindBtn =  (Button)findViewById(R.id.button4);
		nextBtn =  (Button)findViewById(R.id.button5);
		intent = new Intent(MainActivity.this, MyService.class).putExtra("name", "kailong");
		startBtn.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				System.out.println("startBtn");
				startService(intent);
			}
		});
		stopBtn.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				System.out.println("stopBtn");
				stopService(intent);
			}
		});
		bindBtn.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				bindService(intent, conn, BIND_AUTO_CREATE);
			}
		});
        unBindBtn.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				unbindService(conn);
			}
		});
       nextBtn.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				startActivity(new Intent(MainActivity.this, FirActivity.class));
			}
		});
		
	}
	private ServiceConnection  conn = new ServiceConnection(){

		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			// TODO Auto-generated method stub
			Log.i(Tag, "-----((MyBinder)service).getData();----MainActivity-->" + ((MyBinder)service).getData());
			Log.i(Tag, "-----onServiceConnected------>");
		}

		@Override
		public void onServiceDisconnected(ComponentName name) {
			// TODO Auto-generated method stub
			Log.i(Tag, "-----onServiceDisconnected------>");
		}
		
	};

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

}

            MyService类是extends Service 
       

package com.example.android_service_lifecycle;

import java.io.ByteArrayInputStream;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;
import android.widget.Toast;

public class MyService extends Service{
	public final static String Tag = "main";
	private int data;
	private MyBinder myBinder = new MyBinder();
	public void onCreate() {
		// TODO Auto-generated method stub
		Log.i(Tag, "onCreate");
		super.onCreate();
	}
	
	private  Handler handler = new Handler() {
		public void handleMessage(Message msg) {
			if (msg.what == 1) {
				data = msg.arg1;
			}
		};
	};
		
	
	public class MyThread implements Runnable{

		@Override
		public void run() {
			for(int i=0;i<1000;i++) {
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				Message message = Message.obtain();
				message.what = 1;
				message.arg1 = i;
				handler.sendMessage(message);
			}
			
			
		}
		
	}
	@Override
	@Deprecated
	public void onStart(Intent intent, int startId) {
		// TODO Auto-generated method stub
		super.onStart(intent, startId);
	}
	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.i(Tag, "onStartCommand" + intent.getStringExtra("name"));
		//一些耗时操作
		new Thread(new MyThread()).start();
		return startId;
	}

	@Override
	public IBinder onBind(Intent intent) {
		// TODO Auto-generated method stub
		Log.i(Tag, "onBind");
		return myBinder;
	}
	
	public class  MyBinder extends Binder {
		public int getData() {
			return data;
		}
	};

	@Override
	public boolean onUnbind(Intent intent) {
		// TODO Auto-generated method stub
		Log.i(Tag, "onUnbind");
		return super.onUnbind(intent);
	}
	
	@Override
	public void onRebind(Intent intent) {
		// TODO Auto-generated method stub
		Log.i(Tag, "onRebind");
		super.onRebind(intent);
	}

	@Override
	public void onDestroy() {
		// TODO Auto-generated method stub
		Log.i(Tag, "onDestroy");
		super.onDestroy();
	}

}
      当点击startBtn时,就会startService(),从而启动MyService,就会打印出下面两句,也就是会执行onCreate()、onStartCommand()方法,kailong这句话是来自activity传给Service,附加在intent里面的,也就是activity向Service通信,所以我们在Service就可以getIntent()拿出来。

      

     当再次点击startBtn时,只会重复执行onStartCommand(),而不会再执行OnCreate(),

   怎么停止呢?也就是点击stopBtn,调用stopService(intent),MyService就会停止下来,只会执行onDestroy()函数。

   2.绑定Service, 点击bindBtn,就会执行bindService(intent, conn, BIND_AUTO_CREATE),从而绑定到intent对应的MyService,也就是会执行onCreate()、onBind()方法,onBind()方法会返回一个IBinder对象,然后回调ServiceConnection类中的onServiceConnected(ComponentName name, IBinder service)方法,这时我们就可以拿到IBinder对象从而实现Service向activity通信。注意绑定的时候没有执行onstartCommand()


同样点击unBindBtn,执行unbindService(conn),从而实现Service解绑,会执行onUnbind(),onDestryoy().

附上官网的流程图

   

   bindService时一次实现activity与Service进行绑定,及时多次调用bindService,也不会再执行onBind(),

而当我们bindService时,是不能用stopService来进行解绑的,此时什么也不会发生,除非调用unBindService,才会实现解绑。一旦bindService,再finish(),就会调用onUnbind()、onDestroy(),也会提示 has leaked ServiceConnection  error.所以有时要记得解绑。

   同样,startService时,是不能调用unbindService进行停止的,一调用就会发生退出,也只能调用stopService才会停止。而当startService然后没有调用stopService就退出程序是不会执行onDestroy(),这时Service就会在后台一直运行,除非我们再调用stopService,

   那么如果我们既startService,又点击了bindService会怎么样呢?这个时候你会发现,不管你是单独点击Stop Service还是Unbind Service,Service都不会被销毁,必要将两个按钮都点击一下,Service才会被销毁。也就是说,StopService只会让Service停止,点击Unbind Service按只会让Service和Activity解除关联,一个Service必须要在既没有和任何Activity关联又处理停止状态的时候才会被销毁。


         一些内容参考http://blog.csdn.net/guolin_blog/article/details/11952435

         Service和Thread到底有什么关系呢?什么时候应该用Service,什么时候又应该用Thread?答案可能会有点让你吃惊,因为Service和Thread之间没有任何关系!之所以有不少人会把它们联系起来,主要就是因为Service的后台概念。Thread我们大家都知道,是用于开启一个子线程,在这里去执行一些耗时操作就不会阻塞主线程的运行。而Service我们最初理解的时候,总会觉得它是用来处理一些后台任务的,一些比较耗时的操作也可以放在这里运行,这就会让人产生混淆了。但是,如果我告诉你Service其实是运行在主线程里的,在MainActivity的onCreate()方法里加入一行打印当前线程id的语句与MyService的onCreate()方法里也加入一行打印当前线程id的语句,对比id你会发觉它们是一样的,所以Service里编写了非常耗时的代码,程序必定会出现ANR。

        其实不要把后台和子线程联系在一起就行了,这是两个完全不同的概念。Android的后台就是指,它的运行是完全不依赖UI的。即使Activity被销毁,或者程序被关闭,只要进程还在,Service就可以继续运行。比如说一些应用程序,始终需要与服务器之间始终连接,就可以使用Service来实现。可是刚刚验证过Service是运行在主线程里的么?在这里一直执行着连接,难道就不会阻塞主线程的运行吗?当然会,但是我们可以在Service中再创建一个子线程,然后在这里去处理耗时逻辑就没问题了。

       额,既然在Service里也要创建一个子线程,那为什么不直接在Activity里创建呢?这是因为Activity很难对Thread进行控制,当Activity被销毁之后,就没有任何其它的办法可以再重新获取到之前创建的子线程的实例。而且在一个Activity中创建的子线程,另一个Activity无法对其进行操作。但是Service就不同了,所有的Activity都可以与Service进行关联,然后可以很方便地操作其中的方法,即使Activity被销毁了,之后只要重新与Service建立关联,就又能够获取到原有的Service中Binder的实例。因此,使用Service来处理后台任务,Activity就可以放心地finish,完全不需要担心无法对后台任务进行控制的情况。


一个比较标准的Service就可以写成:

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
	new Thread(new Runnable() {
		@Override
		public void run() {
			// 开始执行后台任务
		}
	}).start();
	return super.onStartCommand(intent, flags, startId);
}

class MyBinder extends Binder {

	public void startDownload() {
		new Thread(new Runnable() {
			@Override
			public void run() {
				// 执行具体的下载任务
			}
		}).start();
	}

}




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值