需求:
众所周知,Service服务是运行于后台进程中的,当服务完成某个功能后,要如何把数据传递到活动或者碎片界面,让用户看得到呢?
方案:
这里我只列举会用的方法,如果你有更高明的方案,欢迎在留言里补充!
一、内部广播
1、创建一个MainApplication类,继承自Application,可以全局调用,代码如下:
import android.app.Application;
import android.content.Context;
import android.content.Intent;
public class MainApplication extends Application {
public static Context mContext;
@Override
public void onCreate() {
super.onCreate();
mContext = getApplicationContext();
}
/**
* 获取全局上下文
* @return
*/
public static Context getAppContext(){
return mContext;
}
/**
* 发送广播消息给MainActivity活动界面
* @param name 标识名
*/
public static void sendBroadcast(String name){
//发送广播消息给MainActivity活动界面
Intent intentBroadcastReceiver = new Intent();
intentBroadcastReceiver.putExtra("name",name);
intentBroadcastReceiver.setAction(MainActivity.ACTION_FRAGMENT_SWITCH);
mContext.sendBroadcast(intentBroadcastReceiver);
}
/**
* 重载方法,用于扩展(广播也可以携带数据)
* @param name 标识名
*/
public static void sendBroadcast(String name,String parameter){
//发送广播消息给MainActivity活动界面
Intent intentBroadcastReceiver = new Intent();
intentBroadcastReceiver.putExtra("name",name);
intentBroadcastReceiver.putExtra("parameter",parameter);
intentBroadcastReceiver.setAction(MainActivity.ACTION_FRAGMENT_SWITCH);
mContext.sendBroadcast(intentBroadcastReceiver);
}
}
2、在MainActivity里声明和注册广播
public class MainActivity extends AppCompatActivity {
//声明一个内部广播实例
public MyBroadcastReceiver broadcastReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//注册广播实例(在初始化的时候)
IntentFilter filter = new IntentFilter();
filter.addAction(ACTION_FRAGMENT_SWITCH);
broadcastReceiver = new FragmentSwitchBroadcastReceiver();
registerReceiver(broadcastReceiver, filter);
}
@Override
protected void onDestroy() {
super.onDestroy();
//销毁广播
unregisterReceiver(broadcastReceiver);
}
/**
* 定义广播接收器
*/
private class MyBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
int id=R.id.main_content;
String name=intent.getStringExtra("name");
String parameter=intent.getStringExtra("parameter");
switch (name){
case "set"://设置
break;
case "about"://关于软件
break;
case"scan"://扫一扫
break;
case"tip"://提示
Toast.makeText(this, parameter, Toast.LENGTH_SHORT).show();
break;
}
}
}
3、当服务需要与活动交互时,直接调用MainApplication里发送广播的方法即可
MainApplication.sendBroadcast("tip","这是一个服务里发送的提示信息");
二、接口辅助类
举例:
我的安卓客户端有一个Socket服务,用于接收服务器端的socket数据,当接收到数据后,我要显示到UI界面上。
1、创建一个接口作为服务与活动传输数据的中间件
public interface SocketListener {
/**
* 接收到数据时
* @param data socket接收到的数据
*/
void onReceivedMessage(Map<String, String> data);
}
2、写一个接口的实现类(辅助类)
/**
* Socket辅助类
* 作用:用于实现数据的回调处理
*/
public class SocketHelper {
//定义一个单例对象
private static SocketHelper instance;
//Socket监听接口
private SocketListener socketListener;
/**
* 单例模式
* 饿汉式(静态常量)
* 优点:这种写法比较简单,就是在类装载的时候就完成实例化,避免了线程同步问题。
* 缺点:在类装载的时候就完成实例化,没有达到Lazy Loading的效果。如果从始至终从未使用过这个实例,则会造成内存的浪费。
* @return
*/
public static SocketHelper getInstance() {
if (instance == null) {
instance = new SocketHelper();
}
return instance;
}
/**
* 收到数据时触发
* @param data socket接收到的数据
*/
public void onReceived(Map<String, String> data) {
if(socketListener != null) {
socketListener.onReceivedMessage(data);
}
}
/**
* 设置监听
*/
public void setSocketListener(SocketListener socketListener) {
this.socketListener = socketListener;
}
3、Activity活动或者Fragment碎片,使用implements引用接口中间件
public class MainActivity extends AppCompatActivity implements SocketListener {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//使用socket帮助类,设置监听接口通知
SocketHelper.getInstance().setSocketListener(this);
}
/**
* 接收到数据时
* @param data socket接收到的数据
*/
@Override
public void onReceivedMessage(Map<String, String> data) {
//在这里处理数据即可
}
}
4、当服务需要与活动交互时,直接调用SocketHelper辅助类的方法即可
SocketHelper.getInstance().onReceived(data);