service相关知识
使用和绑定service
首先得知道service是什么
http://www.cnblogs.com/newcj/archive/2011/05/30/2061370.html
这上面讲的比较清楚
首先我们创建一个service
然后回到main,创建四个button分别代表,开始,结束,绑定,接触绑定
然后设定监听器,关于监听器,可以使用批量定义的方法
findViewById(R.id.button1).setOnClickListener(this); findViewById(R.id.button2).setOnClickListener(this); findViewById(R.id.button3).setOnClickListener(this); findViewById(R.id.button4).setOnClickListener(this);
public void onClick(View v) { switch (v.getId()){ case R.id.button1: startService(intent); break; case R.id.button2: stopService(intent); break; case R.id.button3: bindService(intent,this,Context.BIND_AUTO_CREATE); break; case R.id.button4: unbindService(this); break; } } @Override public void onServiceConnected(ComponentName name, IBinder service) { } @Override public void onServiceDisconnected(ComponentName name) { } }
startService(intent);
public int onStartCommand(Intent intent, int flags, int startId) { new Thread(){ @Override public void run() { super.run(); while (true) { System.out.println("service..."+a++); try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); return super.onStartCommand(intent, flags, startId); }在service中写这个,
- 启动service的时候,onCreate方法只有第一次会调用,onStartCommand和onStart每次都被调用。onStartCommand会告诉系统如何重启服务,
- 如判断是否异常终止后重新启动,在何种情况下异常终止
然后点击start,会自动运行,如果退出app,还是会继续运行
但是你会发现,如果写在onStartCommand中,当你点击多次开始服务的时候,他是会启动不同的线程来完成
所以将其写在public void onCreate() 中,onCreat只在开始时运行一次,所以当你多次点击开始他也只会运行一次
说明service会在后台运行,所以很多需要在后台写的代码都可以在service中
我们可以改写代码
用来看他什么时候停止public void onCreate() { super.onCreate(); running=true; new Thread(){ @Override public void run() { super.run(); while (running) { System.out.println("service..."+a); try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); }@Overridepublic void onDestroy() { running=false; super.onDestroy();}
当停止时,会终止运行。
还是用我们的老朋友Intent
在button的响应代码中加入
intent.putExtra("data",editText.getText().toString());
用以实现数据共享
我们可以在MyService,中找到
public int onStartCommand(Intent intent, int flags, int startId) {可以用它接收Intent
public int onStartCommand(Intent intent, int flags, int startId) { a=intent.getStringExtra("data"); return super.onStartCommand(intent, flags, startId); }在MyServies中接受
case R.id.button3: bindService(intent,this,Context.BIND_AUTO_CREATE); break;
onServiceConnected会在绑定时运行
onServiceDisconnected会在程序崩溃时运行
我们可以看到IBinder service链接service时,会自动启动onServiceConnected,IBinder在MyService中
public IBinder onBind(Intent intent) { return new Binder(); }为了方便,我们可以重写类public class Binder extends android.os.Binder{ public void setData(String data){ MyService.this.a=data; } }然后回到MainActivity,private MyService.Binder binder;定义好一个Binder,private MyService.Binder binder;当绑定时,将两个binder绑定@Override public void onServiceConnected(ComponentName name, IBinder service) { binder= (MyService.Binder) service; }新添加一个按钮,用来同步数据case R.id.button5: binder.setData(editText.getText().toString()); break;可以完成数据的同步
startService()和bindService()两种模式是完全独立的,如果service还没启动,bindService会启动服务。
点击bind时,系统也会调用Myservice中的onCreat,
使用destroy并不能关掉
如果共享数据
那么后台的传输解决 解决了,又有一个 新的问题,如何将后台数据显示在activity中,这里就要用到android的回调机制
private CallBack callBack; public void setCallBack(CallBack callBack) { this.callBack = callBack; } public CallBack getCallBack() { return callBack; } public interface CallBack{ void onDataChange(String args); }
然后再Binder中添加getService方法,使得外界可以获得MyService
public class Binder extends android.os.Binder{ public void setData(String data){ MyService.this.a=data; } public MyService getService(){ return MyService.this; } }
在activity中
@Override public void onServiceConnected(ComponentName name, IBinder service) { binder= (MyService.Binder) service; binder.getService().setCallBack(new MyService.CallBack() { @Override public void onDataChange(String args) { tv.setText(args); } });我本来想直接tv.setText(args);
结果发现不行,程序是由线程调用的,线程直接调用UI资源是会报错的。在Android的UI开发中,我们经常会使用Handler来控制主UI程序的界面变化。有关Handler的作用,我们总结为:与其他线程协同工作, 接收其他线程的消息并通过接收到的消息更新主UI线程的内容。
Handler handler=new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); } };Message是线程之间传递信息的载体,包含了对消息的描述和任意的数据对象。public void onDataChange(String args) { Message message=new Message(); Bundle bundle=new Bundle(); bundle.putString("data",args); message.setData(bundle); handler.sendMessage(message); }这样可以UI线程的通信