android之service
来源:互联网 发布:火狐浏览器优化版 编辑:程序博客网 时间:2024/05/16 23:48
刚开始学service的时候就在想,service于thread的区别。后来发现service根本就不是thread!!!原来service是直接运行在主线程里面的,也就是UI主线程。明白了service于thread的区别之后又有新问题,为什么要用service?直接用thread不行吗?反正都是执行长时间任务。后来发现的确是有原因的。这么说吧,thread是独立运行在程序中的,也就是和activity没有半毛钱关系,当activity被销毁的时候thread可能还在运行。而service不一样,当activity销毁的时候你可以选择连同销毁service。而且你没有办法在不同的activity操作同一thread。但service可以。所以这时候就需要service,一般的方法在service里创建thread,让service来控制thread。这样就形成了可能你的activity还没启动的时候thread已经start了,也可以让不同的activity来控制同一个service,进而来获取thread中处理的数据。
不过这里我有个问题,我在做小程序的时候,在service里创建了一个thread,当service销毁的时候thread还在运行,thread是个死循环,这个该怎么关闭,感觉这个是thread里的问题。虽然我用了其他办法解决了,但这块不知道有没有什么直接的办法可以杀死service里的正在运行的thread。
还有一点,service必须运行在UI主线程,不能在子线程运行,但可以在service里创建子线程。切记!
service的表现方式也分为两种:
1.startService。
生命周期:onCreat -- onStartCommand -- Service Runing -- stop -- onDestory
使用startService()方法启用服务,调用者与服务之间没有关连,即使调用者退出了,服务仍然运行。
最重要的是startService开启的service不能和activity交互,也就是说不能进行数据传递,除非使用异步消息处理机制。
下面是代码,首先是service里的
public class MyService extends Service { public MyService() { } @Override public IBinder onBind(Intent intent) { throw new UnsupportedOperationException("Not yet implemented"); } @Override public void onCreate() { //这里可以初始化一些数据 super.onCreate(); } @Override public int onStartCommand(Intent intent, int flags, int startId) { /** * 这里放进行的任务,比如下载网络数据等等。 * 一定要记得记得创建一个子线程,一是为了方便用户体验,二是有些任务需要在子线程里进行,例如下载图片。 * 任务完成后记得在这个方法里调用stopSelf()来关闭service服务。 * 也可以在activity中调用stopService(intent),但是startService不能和activity交互, * 并不知道什么时候service里的任务已经完成,所以最好还是让service本身来关闭自己。 * 同时stopService(intent)是外部调用,不利于代码结构。 * 最后记住,关闭service也要在主线程进行,可以在主线程创建一个关闭service的handler, * 让子线程来发送关闭请求到handler。 */ return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { //这里可以进行一些资源的释放 super.onDestroy(); }}然后是activity里的
MyService myService = new MyService(); Intent intent = new Intent(MainActivity.this, MyService.class); MainActivity.this.startService(intent);
这样一个service就启动成功了。这种方式启动的service比较简单。
2.bindService
生命周期:onCreat -- onBind -- Client Bound Service -- onUnbind -- onDestory
使用bindService()方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止。
最重要的是bindService绑定的service可以和activity交互,能进行数据传递。
下面是代码,首先是service里的
public class MyService extends Service { //上转型对象的方式来实例化,MyBinder不行吗? private final Binder myBinder = new MyBinder(); public MyService() { } /** * 一定要在onBind方法中返回当前Binder对象,这样client根据返回的Binder对象来获取当前service * 不过这里为什么返回的是IBinder类型?而不是Binder类型? * Binder是一个具体类,具有其自己的功能,继承Binder可以使用Binder原有功能,只对你需要的方法做修改 * IBinder是个接口,可以让你的类当作Binder来用,但是所有的具体功能都需要你自己编写逻辑。 * 意思就是ServiceConnection里传回去的是一个IBinder接口对象,我们需要回调成MyBinder对象,进而获取service * 可是为什么要设计的这么麻烦,难道有什么好处我还不知道?有待挖掘。。。 */ @Override public IBinder onBind(Intent intent) { return myBinder; } /** * 这个类里必须有一个共有的方法要返回当前service本身的实例,给client调用, * 这就是问什么多个activity可以访问同一个bindService实例的原因 * MyBinder类和上面的onBind方法是用来给调用者获取service实例的 */ class MyBinder extends Binder { //获取当前Service实例 public MyService getService() { return MyService.this; } //Binder里的onTransact方法用于和调用组件进行交互 @Override protected boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { //接受activity传进来的值 String string1 = data.readString(); //将传进来的data进行操作 String string2 = string1 + "和"; //这里可以将service的后台任务处理的数据返回哦 reply.writeString(string2 + getRandom() + ""); return super.onTransact(code, data, reply, flags); } } /** * client获取了当前service对象后,就可以操作这些执行任务的方法, * 可以是获取网络信息等,记得最好要在方法里创建子线程????? * 这里是返回一个随机数 */ int getRandom() { Random random = new Random(); return random.nextInt(30); } @Override public void onCreate() { //这里可以初始化一些数据 super.onCreate(); } @Override public void onDestroy() { //这里可以进行一些资源的释放 super.onDestroy(); }}然后是调用者activity里面的
public class MainActivity extends AppCompatActivity { Button button1, button2; TextView textView1, textview2; //service实例 MyService myService; //服务对象 MyService.MyBinder myBinder; //默认是不绑定service的 boolean isBind = false; //官方推荐我们在这里绑定service,当然也可以动态绑定service,具体参见activity生命周期 @Override protected void onStart() { super.onStart(); Intent intent = new Intent(MainActivity.this, MyService.class); //绑定service,参数是intent,serviceConnection,和flag bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView1 = (TextView) findViewById(R.id.textview1); textview2 = (TextView) findViewById(R.id.textview2); button1 = (Button) findViewById(R.id.button1); button2 = (Button) findViewById(R.id.button2); //按钮一调用service方法,获取随机数 button1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (isBind) { int result = myService.getRandom(); textView1.setText(result + ""); } } }); //按钮二获得service的回传值 button2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //将textView1中的内容传进去 String string = textView1.getText().toString(); //往service中传递值的对象,必须是序列化的对象 Parcel data = Parcel.obtain(); //在传递对象里放入数据 data.writeString(string); //用来接受传回来的序列化对象 Parcel replay = Parcel.obtain(); try { /** * transact是一个可以往service里传递数据并返回结果的方法,用于service和调用者交互数据 * 第一个参数只有两个,一个是FIRST一个是LAST * 第二个参数是要传递的Parcel对象 * 第三个参数是传回来的parcel对象 * 第四个参数是int flag,通常都是0 */ myBinder.transact(IBinder.LAST_CALL_TRANSACTION, data, replay, 0); } catch (RemoteException e) { e.printStackTrace(); } //将返回的值取出 String string2 = replay.readString(); textview2.setText(string2); } }); } //在这里销毁service,也是官方推荐 @Override protected void onStop() { super.onStop(); if (isBind) { unbindService(serviceConnection); isBind = false; } } /** * 这个方法充当着client和service的桥梁,要想操作service不能new一个service, * 因为new出来的不是同一个实例,不能保证数据同步等,这时候我们就需要一个方法来获取当前service的实例, * ServiceConnection类就能解决这个问题,还能被多个context调用来获取相同的service实例。 */ ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { //根据传进来的IBinder参数获取MyService.MyBinder对象 myBinder = (MyService.MyBinder) service; //根据myBinder获取MyService对象 myService = myBinder.getService(); //告诉是上面的变量已经绑定了 isBind = true; } @Override public void onServiceDisconnected(ComponentName name) { isBind = false; } };}这样就是bindservice的运行模式了。
除了这两个service的表现方式外,service有五个已知的子类:AbstractInputMethodService, AccessibilityService, IntentService, RecognitionService, WallpaperService
intentService貌似很常用,感觉就是普通的service加上handler,thread和stopSelf。意思就是这个service不用在创建线程,不用创建handler机制,不用手动停止service,通常用于单线程的操作。
还有一个是service里的AIDL进程间通信,学的有点稀里糊涂,里面涉及到一个服务器的概念,主要是web没学过,html也不太懂,就知道AIDL貌似和android里的四大组件之contentProvider有相似之处,感觉应用领域比较窄,就没深入研究,等以后用到的时候再回来看看吧。
- android Service 之Bound Service
- Android Service 之Bound Service
- android Service 之Bound Service
- android Service 之Bound Service
- Android之Service相关
- Android基本之Service
- Android 之 service
- Android学习之Service
- Android Service 之 AIDL
- android之Service
- android组件之Service
- Android学习之Service
- Android之service
- Android之Service
- Android基础之Service
- Android之Service&BroadCastReceiver
- 浅谈android 之 service
- android之Service
- StringBuffer传引用,删除原值,改为新值
- 自动化测试
- js+css制作悬浮提示层弹出特效
- cocos3.4 lua 工程打包为apk后运行一段时间闪退的问题
- 用一个函数实现遍历一个文件夹下的所以文件和子文件夹
- android之service
- 水仙题-hdu2054
- Oracle的表级锁
- 顺时针打印矩阵
- leetcode Valid Sudoku
- POJ 3616 Milking Time(DP)
- Linux vmstat命令实战详解
- Http请求中Content-Type讲解以及在Spring MVC中的应用
- 日常事务处理