在Android中,Activity主要负责前台页面的展示,Service主要负责需要长期运行的任务,所以在我们实际开发中,就会通常遇到Activity与Service之间的通信,我们一般在Activity中启动后台Service,通过Intent来启动,Intent中我们可以传递数据给Service,但是我们Service执行某些操作之后想要更新UI线程,我们可以通过以下方法。
通过binder对象
当Activity通过调用 bindService(Intent service, ServiceConnection conn, int flags)
,我们可以在Activity中得到一个Ibinder的对象实例,可以在Ibinder中得到数据。
- 在Service的onBind(Intent intent)
的方法中,返回一个自定义的Binder对象
class MusicBinder extends Binder {
public int getProgress() { // 返回进度
if (player.isPlaying()) {//这儿是音乐播放器在播放
return player.getCurrentPosition();
} else {
return 0;
}
}
}
- 在Activity中重写ServiceConnection中
onServiceConnecte(ComponentName name, Ibinder service)
就是上面定义的对象,可以强转,然后调用相应的方法
private ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
binder = (MusicBinder) service;
Log.i("MainActivity", "----"+binder.getProgress());
}
};
通过Braodcast广播的形式
思路:当我们进度发生变化的时候我们发送一条广播,然后在Activity注册广播接收器,接收到广播之后更新ProgressBar
在Activity中定义并注册这个广播
class MyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
int progress = intent.getIntExtra("progress", 0);
pb_1.setProgress(progress);
tv_1.setText(progress + "%");
}
}
在Service中启动线程,不断发送广播
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new Thread() {
public void run() {
Intent i1 = new Intent();
i1.setAction("myrecevier");
for (int i = 0; i < 101; i++) {
i1.putExtra("progress", i);
sendBroadcast(i1);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//此处应该发消息关闭
};
}.start();
return super.onStartCommand(intent, flags, startId);
}
利用hanlder传递消息
- 在activity中新建一个handler对象,重写
handleMessage()
方法,并定义一个可以得到当前Activity静态引用和handler对象的引用,然后在广播中得到这个handler用来发送消息。
private Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case 1:
tv_2.setText("" + msg.arg1);
break;
}
};
};
public Handler getHandler() {
return handler;
}
//静态的引用
private static MainActivity mMainActivity = null;
//重写空的构造方法
public MainActivity() {
mMainActivity = this;
}
//静态方法用来得到当前类的引用
public static MainActivity getmMainActivity() {
return mMainActivity;
}
服务中启动线程来发送数据
private Thread thread = new Thread(){
public void run() {
while (flag) {
index ++;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.i("----------", "-------------------"+index);
Handler handler = MainActivity.getmMainActivity().getHandler();
Message msg = handler.obtainMessage();
msg.what = 1;
msg.arg1 =index;
handler.sendMessage(msg);
}
};
};
接口回调的方式
- 在Service中定义一个CallBack接口中含有抽象方法,包含需要传输的数据
- 重写MyBinder的时候定义一个CallBack对象和,
setCallBack(CallBack back)
方法 如下
import java.util.Random;
import android.app.Service;
import android.content.Intent;
import android.graphics.Color;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
public class ServiceDemo extends Service {
private int[] bgColor = { Color.RED, Color.CYAN, Color.LTGRAY, Color.GRAY };
@Override
public void onCreate() {
super.onCreate();
Log.i("------ServiceDemo", "----ServiceDemo");
}
private MyBinder binder;
@Override
public IBinder onBind(Intent intent) {
Log.i("--------bind", "----BInd");
binder = new MyBinder();
new Thread(){
public void run() {
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
binder.callBack.back("红红火火恍恍惚惚红红火火恍恍惚惚" + i); //接口回调的方式,可以
}
};
}.start();
return binder;
}
interface CallBack {
public void back(String str);
}
class MyBinder extends Binder {
private Random random = new Random();
CallBack callBack;
public void setCallBack(CallBack callBack) {
this.callBack = callBack;
}
public int getBg() {
return bgColor[random.nextInt(bgColor.length)];
}
}
@Override
public void onDestroy() {
Log.i("--------onDestroy", "----onDestroy");
super.onDestroy();
}
@Override
public boolean onUnbind(Intent intent) {
Log.i("--------onUnbind", "----onUnbind");
return super.onUnbind(intent);
}
}
- 在Activity中用bindService方法绑定,然后重写ServiceConncection方法,得到binder对象,然后setCallBack就好了。
MyBinder binder = null;
ServiceConnection conn = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
Log.i("MainActivity", "----onServiceDisconnected");
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i("MainActivity", "----onServiceDisconnected");
binder = (MyBinder) service;
binder.setCallBack(new CallBack() {
@Override
public void back(String str) {
Log.i("MainActivity", str);
}
});
}
};