Service的使用
2016-05-16 22:52
369 查看
Service是安卓开发的四大组件之一,没有用户界面,一直运行于后台。Service可用于在执行一些耗时或者不需要界面的后台操作,比如播放音乐。
这里我来记录一下Service的使用方法,包括Service的启动、绑定、通信等操作。
首先新建一个MyService继承Service,重写父类的各回调方法。为了方便观察各方法的执行顺序,为各个方法加上日记输出语句。
修改默认布局,为之添加两个按钮,分别用于启动和停止服务。
修改MainActivity类,监听两个按钮的点击动作,通过Intent来启动或停止服务。
程序运行界面如下:
点击启动服务按钮,日志输出如下:
点击停止服务按钮,日志输出如下:
可以看到,启动服务并没有执行到onBind方法。而且,当多次点击启动服务按钮时,onCreate方法只会被执行一次,而onStartCommand方法会被调用多次。
为了模拟后台操作,修改onCreate方法,让它新建一个线程,用于不断输出语句。
首先声明三个属性
每当执行到onCreate方法时,就会新建一个子线程用于输出data,而且每输出一句就休眠一秒。
又因为开启了子线程,如果不主动停止的话,就算执行了onDestroy方法,子线程也会继续在后台执行,所以修改onDestroy
这样,当执行onDestroy方法时,子线程也就不会继续输出了。
服务除了启动外,也有用于绑定的形式,为默认布局添加两个按钮,分别用于绑定服务以及取消绑定服务。
修改MainActivity的onClick方法
bindService方法用于绑定服务,参数二需要传入一个ServiceConnection接口的实现类,让MainActivity类实现之,所以传入this
ServiceConnection接口需要实现的方法如下所示
此外,绑定服务需要重写onBind(Intent intent)方法,返回一个IBinder类型的对象,这里可以自己声明一个实现了Binder接口的MyBind内部类。
启动程序,点击绑定服务按钮,可以看到日志输出如下所示,绑定服务后并没有执行onStartCommand方法,而是执行了onBind方法。
此外,我们该如何与服务进行通信呢,比如说修改Service的输出语句。
其实,onServiceConnected(ComponentName name, IBinder service)方法会在服务绑定成功的时候执行,当中的IBinder 参数即为MyService中onBind方法返回的对象,通过它,我们就可以与服务进行通信了。
为默认布局增添一个EditText,用于输入想要日志输出的语句,此外还要一个Button,用于同步数据。
修改MyBinder类,为之增添一个方法,用于修改输出信息。
在MainActivity中声明一个MyBinder对象,通过onServiceConnected方法就可以获得onBind返回的对象的引用了。
修改MainActivity的onClick方法,添加一个判断语句,用于修改输出语句
程序运行界面如下:
点击绑定服务,因为编辑框中已经有默认文本,所以直接点击同步数据,日志输出如下:
可以看到输出语句成功修改了。
既然可以在Activity中向Service传递数据,那Service又该如何向Activity返回数据呢?
用以上的方法似乎不行,不过可以通过回调方法来实现。
在默认布局中增添一个TextView,用于显示当前的输出语句。
为MyBinder方法增添一个返回服务对象引用的方法
声明一个接口以及一个接口对象
修改onCreate方法,当callBack不为空时,每执行一次输出语句就调用一次editTextView方法
在MainActivity中声明一个MyService.CallBack对象
修改onServiceConnected方法传递引用
因为子线程中不允许更新UI组件,函数应写为
则程序运行结果如下所示
这里我来记录一下Service的使用方法,包括Service的启动、绑定、通信等操作。
首先新建一个MyService继承Service,重写父类的各回调方法。为了方便观察各方法的执行顺序,为各个方法加上日记输出语句。
public class MyService extends Service { public MyService() { } @Override public void onCreate() { super.onCreate(); Log.e("TAG", "onCreate方法被调用"); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.e("TAG", "onStartCommand方法被调用"); return super.onStartCommand(intent, flags, startId); } @Override public void onDestroy() { super.onDestroy(); Log.e("TAG", "onDestroy方法被调用"); } @Override public IBinder onBind(Intent intent) { Log.e("TAG", "onBind方法被调用"); throw new UnsupportedOperationException("Not yet implemented"); } }
修改默认布局,为之添加两个按钮,分别用于启动和停止服务。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:orientation="vertical" tools:context="com.example.zy.myservice.MainActivity"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/btnStartService" android:text="启动服务"/> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/btnStopService" android:text="停止服务"/> </LinearLayout>
修改MainActivity类,监听两个按钮的点击动作,通过Intent来启动或停止服务。
public class MainActivity extends AppCompatActivity implements View.OnClickListener { private Button btnStartService; private Button btnStopService; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); } public void init() { btnStartService = (Button) findViewById(R.id.btnStartService); btnStopService = (Button) findViewById(R.id.btnStopService); btnStartService.setOnClickListener(this); btnStopService.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btnStartService: startService(new Intent(this, MyService.class)); break; case R.id.btnStopService: stopService(new Intent(this, MyService.class)); break; } } }
程序运行界面如下:
点击启动服务按钮,日志输出如下:
点击停止服务按钮,日志输出如下:
可以看到,启动服务并没有执行到onBind方法。而且,当多次点击启动服务按钮时,onCreate方法只会被执行一次,而onStartCommand方法会被调用多次。
为了模拟后台操作,修改onCreate方法,让它新建一个线程,用于不断输出语句。
首先声明三个属性
private String data="默认信息"; private int index; private boolean flag;
每当执行到onCreate方法时,就会新建一个子线程用于输出data,而且每输出一句就休眠一秒。
public void onCreate() { super.onCreate(); Log.e("TAG", "onCreate方法被调用"); flag=false; new Thread(){ @Override public void run() { super.run(); while(flag){ index++; System.out.println(index+" : "+data); try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); }
又因为开启了子线程,如果不主动停止的话,就算执行了onDestroy方法,子线程也会继续在后台执行,所以修改onDestroy
@Override public void onDestroy() { super.onDestroy(); flag = false; Log.e("TAG", "onDestroy方法被调用"); }
这样,当执行onDestroy方法时,子线程也就不会继续输出了。
服务除了启动外,也有用于绑定的形式,为默认布局添加两个按钮,分别用于绑定服务以及取消绑定服务。
修改MainActivity的onClick方法
@Override public void onClick(View v) { switch (v.getId()) { case R.id.btnStartService: startService(new Intent(this, MyService.class)); break; case R.id.btnStopService: stopService(new Intent(this, MyService.class)); break; case R.id.btnBindService: bindService(new Intent(this,MyService.class),this, Context.BIND_AUTO_CREATE); break; case R.id.btnUnbindService: unbindService(this); } }
bindService方法用于绑定服务,参数二需要传入一个ServiceConnection接口的实现类,让MainActivity类实现之,所以传入this
ServiceConnection接口需要实现的方法如下所示
@Override public void onServiceConnected(ComponentName name, IBinder service) { } @Override public void onServiceDisconnected(ComponentName name) { }
此外,绑定服务需要重写onBind(Intent intent)方法,返回一个IBinder类型的对象,这里可以自己声明一个实现了Binder接口的MyBind内部类。
public class MyBinder extends Binder { } @Override public IBinder onBind(Intent intent) { Log.e("TAG", "onBind方法被调用"); return new MyBinder(); }
启动程序,点击绑定服务按钮,可以看到日志输出如下所示,绑定服务后并没有执行onStartCommand方法,而是执行了onBind方法。
此外,我们该如何与服务进行通信呢,比如说修改Service的输出语句。
其实,onServiceConnected(ComponentName name, IBinder service)方法会在服务绑定成功的时候执行,当中的IBinder 参数即为MyService中onBind方法返回的对象,通过它,我们就可以与服务进行通信了。
为默认布局增添一个EditText,用于输入想要日志输出的语句,此外还要一个Button,用于同步数据。
修改MyBinder类,为之增添一个方法,用于修改输出信息。
public class MyBinder extends Binder { public void setData(String data) { MyService.this.data = data; } }
在MainActivity中声明一个MyBinder对象,通过onServiceConnected方法就可以获得onBind返回的对象的引用了。
private MyService.MyBinder myBinder; @Override public void onServiceConnected(ComponentName name, IBinder service) { this.myBinder= (MyService.MyBinder) service; }
修改MainActivity的onClick方法,添加一个判断语句,用于修改输出语句
case R.id.btnSyncData: if (myBinder != null) { myBinder.setData(editText.getText().toString()); }
程序运行界面如下:
点击绑定服务,因为编辑框中已经有默认文本,所以直接点击同步数据,日志输出如下:
可以看到输出语句成功修改了。
既然可以在Activity中向Service传递数据,那Service又该如何向Activity返回数据呢?
用以上的方法似乎不行,不过可以通过回调方法来实现。
在默认布局中增添一个TextView,用于显示当前的输出语句。
为MyBinder方法增添一个返回服务对象引用的方法
public class MyBinder extends Binder { public void setData(String data) { MyService.this.data = data; } public MyService getMyService() { return MyService.this; } }
声明一个接口以及一个接口对象
public interface CallBack { public void editTextView(String data); } public CallBack callBack;
修改onCreate方法,当callBack不为空时,每执行一次输出语句就调用一次editTextView方法
@Override public void onCreate() { super.onCreate(); Log.e("TAG", "onCreate方法被调用"); flag = true; new Thread() { @Override public void run() { super.run(); while (flag) { index++; String outPutData=index + " : " + data; System.out.println(outPutData); if(callBack!=null){ callBack.editTextView(outPutData); } try { sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); }
在MainActivity中声明一个MyService.CallBack对象
修改onServiceConnected方法传递引用
@Override public void onServiceConnected(ComponentName name, IBinder service) { this.myBinder = (MyService.MyBinder) service; ((MyService.MyBinder) service).getMyService().callBack = this.callBack; }
因为子线程中不允许更新UI组件,函数应写为
private MyService.CallBack callBack = new MyService.CallBack() { @Override public void editTextView(String data) { Message msg = new Message(); msg.obj = data; handler.sendMessage(msg); } }; private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); textView.setText(msg.obj.toString()); } };
则程序运行结果如下所示
相关文章推荐
- jQuery基础教程-第8章-002Adding jQuery object methods
- C++常见错误中英文对照表
- POJ2411(Mondriaan's Dream)
- iOS基础开发-UI基础之UIScrollview
- Github学习之GooeyMenu实现粘性菜单
- Struts中的OGNL表达式语言1/Struts标签与OGNL表达式语言实例演练2/Struts2常用标签总结3
- MySQL的CRUD操作+使用视图
- 判断一个单链表是否有环及环的链接点(转)
- Lua学习笔记Day3-Lua实现类、Lua面向对象
- 逆元的使用
- SharedPrefercences存储
- UVa 1451 平均值 数形结合
- 剑指offer02--入栈和出栈
- 第八次作业
- C++随笔:.NET CoreCLR之GC探索(2)
- Spark中组件Mllib的学习6之ALS测试(apache spark 含隐式转换)
- 连续子数组的最大和
- C++ STL--stack/queue 的使用方法
- [Swift自学之旅一]Swift的一些基本知识
- OSPF协议