Service做为Android四大组件之一,才疏学浅的我在近期对它有了点粗鄙的认识,真诚的我就迫不及待地想让大家了解俺对Service的理解,有错误的地方还请大家多多指教。。。
Service它是一种长生命周期的,没有可视化界面,运行于后台的一种服务程序。平时我们手机上很多应用都在后台执行。这也是service重要的原因,除此之外,它也是用来执行需要执行长时间的任务。因为我们知道android是单线程,如果在主线程中跑较长时间任务的话会堵塞主线程。所以我们有时候还需要主线程和Activity之间的通信。
基本的Service用法我就不详细介绍了,先看图解:
下面我们通过在service端实现比较两个数大小的功能,在主线程显示更大的数。
MyBinderService
package com.example.lab4exam03;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
public class MyBinderService extends Service{
int num1;
int num2;
public MyBinderService(){
}
//先创建Service,且只会执行一次
@Override
public void onCreate() {
super.onCreate();
}
//销毁Service
@Override
public void onDestroy() {
super.onDestroy();
}
//执行Service,会执行很多次
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
//接触绑定,因为我们除了通过StartService可以开启Service还可以通过绑定自动创建
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
//必须实现的方法,也是最重要的的方法
@Override
public IBinder onBind(Intent intent) {//IBinder是一个接口,而Binder实现了这个接口
return new MyBinder();
}
public class MyBinder extends Binder{
public int IntCompare(){//比较,返回较大值
return (num1 >= num2 ? num1 : num2);
}
public void setData(int num1, int num2){//将Activity里的数据通过IBinder传到Service
MyBinderService.this.num1 = num1;
MyBinderService.this.num2 = num2;
}
}
}
采用AsynvTask的MainActivity
package com.example.lab4exam03;
import com.example.lab4exam03.MyBinderService.MyBinder;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends Activity {
TextView tv;
Button bt;
Intent intent;
Handler handler;
EditText ed1;
EditText ed2;
MyBinder binder;
int num1,num2;
//为绑定服务的参数
ServiceConnection conn = new ServiceConnection(){
//最精华的部分,就是把安插在Service里的间谍iBinder找过来获取或者传递数据
@Override
public void onServiceConnected(ComponentName arg0, IBinder iBinder) {
binder = (MyBinder) iBinder;
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
// TODO Auto-generated method stub
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获取控件
ed1 = (EditText)findViewById(R.id.editText1);
ed2 = (EditText)findViewById(R.id.editText2);
tv = (TextView) this.findViewById(R.id.textView3);
bt = (Button) this.findViewById(R.id.button1);
intent = new Intent(this,MyBinderService.class);
//绑定服务,这里的Intent和onstartCommand参数里的intent是同一个,所以我们也能通过这种方式
//向Service传递数据
this.bindService(intent, conn, BIND_AUTO_CREATE);
num1 = Integer.parseInt(ed1.getText().toString());
num2 = Integer.parseInt(ed2.getText().toString());
}
/*
* 异步类的三个参数
* 第一个表示执行doInBackground方法传进来的参数类型
* 第二个是进度值的类型
* 第三个是执行完任务返回的类型,也就是onPostExecute的参数类型
*/
class MyAsynvTask extends AsyncTask{
//执行一些任务前的UI操作
@Override
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
}
@Override
protected void onPostExecute(Integer i) {//UI操作,将textview的内容设置成最大值
tv.setText(i);
}
@Override
protected Integer doInBackground(Integer... num) {//返回最大值到onPostExecute()
binder.setData(num[0], num[1]);
return binder.IntCompare();
}
}
public void click(View view){
new MyAsynvTask().execute(num1,num2);//启动异步,类似thread.start()方法,
}
}
采用Handler的MainActivity
package com.example.lab4exam01;
import com.example.lab4exam01.MyBinderService.MyBinder;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends Activity {
TextView tv;
Button bt;
Intent intent;
Handler handler;
EditText ed1;
EditText ed2;
MyBinder binder;
ServiceConnection conn = new ServiceConnection(){
@Override
public void onServiceConnected(ComponentName arg0, IBinder iBinder) {
binder = (MyBinder) iBinder;
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
// TODO Auto-generated method stub
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ed1 = (EditText)findViewById(R.id.editText1);
ed2 = (EditText)findViewById(R.id.editText2);
tv = (TextView) this.findViewById(R.id.textView3);
bt = (Button) this.findViewById(R.id.button1);
intent = new Intent(this,MyBinderService.class);
handler = new Handler();
//启动服务
this.bindService(intent, conn, BIND_AUTO_CREATE);
//startService(intent);
}
Thread thread = new Thread(new Runnable(){
@Override
public void run() {
if(binder != null) {
int num1 = Integer.parseInt(ed1.getText().toString());
int num2 = Integer.parseInt(ed2.getText().toString());
binder.setData(num1, num2);
}
tv.setText("较大的数为:"+binder.IntCompare());
}
});
public void click(View view){
handler.post(thread);
}
}
activity_main.XML
AndroidManifest.xml
但是假如我们不通过绑定服务来启动service,而是通过startService方法的话,我们就无法获得Ibinder对象,也就无法通过Ibinder对象进行Service和Activity之间的通信。所有我们换一种方式
1.Activity-------(Intent)------->Service
2.Service------(Broadcast)------->Activity
MyBinderService
package com.example.lab4exam02;
import android.app.Service;
import android.content.Intent;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
public class MyBinderService extends Service{
String num1;
String num2;
public MyBinderService(){
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
num1 = intent.getStringExtra("num1");
num2 = intent.getStringExtra("num2");
Log.d("tag","1");
//新建intent发送广播
if((num1 == null || num2 == null)||(num1.trim().length() <= 0 || num2.trim().length() <= 0)){
//如果文本框无内容就不是发送广播
}
else{
Intent intent1 = new Intent();//新建一个intent用来发送广播
intent1.setAction("receiver");//设置广播的Action
intent1.putExtra("result", Intcompare());
sendBroadcast(intent1);
}
return super.onStartCommand(intent, flags, startId);
}
public String Intcompare(){//比较方法
return Integer.parseInt(num1) >= Integer.parseInt(num2) ? num1 : num2;
}
@Override
public boolean onUnbind(Intent intent) {
return super.onUnbind(intent);
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
MainActivity
package com.example.lab4exam02;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends Activity {
TextView tv;
Button bt;
Intent intent;
Handler handler;
EditText ed1;
EditText ed2;
String result;
public class MyReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context arg0, Intent intent) {
MainActivity.this.result = intent.getStringExtra("result");
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ed1 = (EditText)findViewById(R.id.editText1);
ed2 = (EditText)findViewById(R.id.editText2);
tv = (TextView) this.findViewById(R.id.textView3);
bt = (Button) this.findViewById(R.id.button1);
handler = new Handler();
}
Thread thread = new Thread(new Runnable(){
@Override
public void run() {
tv.setText("最大值为"+result);//设置textview的值
}
});
public void click(View view){
//向intent里传数据
intent = new Intent(MainActivity.this,MyBinderService.class);
intent.putExtra("num1", ed1.getText().toString());
intent.putExtra("num2", ed2.getText().toString());
//必须在输入文本框内容之后再启动Service,我们也可以通过判断文本框是否为空来StartService
startService(intent);
handler.post(thread); //调用线程
}
}
AndroidManifest.xml静态加入广播接收器
完美!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!