2021SC@SDUSC
public class CabinetService extends Service {}
创建一个CabinetService类,继承自Service类
类中的具体内容分析如下:
private String TAG = CabinetService.class.getSimpleName();
public class LocalBinder extends Binder {
public CabinetService getService() {
return CabinetService.this;
}
}
首先创建Binder对象,返回给客户端即Activity使用,提供数据交换的接口,声明一个方法,getService此方法为提供给客户端调用。在方法中,返回当前对象LocalService,这样我们就可在客户端端调用Service的公共方法了。
int mStartMode;
IBinder mBinder;
boolean mAllowRebind;
定义的三个变量依次代表:标识服务如果被杀死之后的行为;绑定的客户端接口;标识是否可以使用onRebind。便于后面精简代码。
public void onCreate() {
EventBus.getDefault().register(this);
MqttUtils.addMqttObserver(new CabinetObserver(this));
Log.e(TAG, "service is created");
MqttSchedule schedule = new MqttSchedule();
schedule.rollMethod();
}
重新定义了onCreate()方法,其中使用了mqtt 定时检测任务
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG, "service is Start");
return mStartMode;
}
调用startService()启动服务时回调
@Override
public IBinder onBind(Intent intent) {
Log.e(TAG, "service is onBind");
return mBinder;
}
通过bindService()绑定到服务的客户端
@Override
public boolean onUnbind(Intent intent) {
Log.e(TAG, "service is onUnbind");
return mAllowRebind;
}
通过unbindService()解除所有客户端绑定时调用
@Override
public void onRebind(Intent intent) {
Log.e(TAG, "service is onRebind");
}
通过bindService()将客户端绑定到服务时调用
@Override
public void onDestroy() {
Log.e(TAG, "service is onDestroy");
EventBus.getDefault().unregister(this);
}
服务不再有用且将要被销毁时调用
@Subscribe(threadMode = ThreadMode.MAIN)
public void snycResult(String msg){
if (msg.equals("overWrite")){
Log.e(TAG, msg);
}else {
Log.e(TAG, "影子同步错误");
//Toast.makeText(this,"影子同步错误:"+msg,Toast.LENGTH_LONG);
}
}
此时ThreadMode 线程模式为MAIN模式,在主线程处理事件 , 如果在子线程发送消息 , 处理消息时会将线程切换成主线程 。主要有两种情况:
- 如果发送事件的线程是 主线程 , 则立刻调用消息处理事件 , 此时 主线程会阻塞 ;
- 如果发送事件的线程是 子线程 , 事件在队列中排队等待传递 , 不会阻塞发布线程 ;
如果数据库被重写,读取数据库所有数据,更新页面;在数据库未被重写的情况下,学长原使用Toast.makeText(this,“影子同步错误:”+msg,Toast.LENGTH_LONG);来重新发送上一步的请求,继续被阻塞的原主进程,但这样使用是报错的。原因分析如下:在子线程中 使用Toast 弹出消息时,去相应的位置去取对象,子线程根本没有初始化就直接取,结果肯定取不到,所以就会抛出此异常,这就是Toast不能直接在子线程中使用,如果使用的话需要添加prepare()函数。
public void update(List<List<NotifyDataDetails>> list){
//list.get(0)是添加的数据的类名和sri
//list.get(1)是更新的数据的类名和sri
//list.get(2)是删除的数据的类名和sri
Log.e(TAG, JSON.toJSONString(list));
List<NotifyDataDetails> addDataDetailsList = list.get(0);
for (NotifyDataDetails addDetail : addDataDetailsList) {
switch (addDetail.getClassName()) {
case "SduMedia":
SduMedia media = (SduMedia) DaoManager.search(new SduMedia(), addDetail.getSri());
if (media == null) {
Log.e(TAG, "收到一个空的media,信息如下: " + JSON.toJSONString(addDetail));
continue;
}
Log.e(TAG, media.getPath());
if (!media.getDownloaded()) {
MinioUtil.downloadByUrl(media.getPath(), (InputStream is) -> {
if (is != null) {
Log.e(TAG, "file separator " + File.separator);
String[] strs = media.getPath().split(File.separator);
String fileName = strs[strs.length - 1];
FileUtil.saveFile(is, fileName);
media.setDownloaded(true);
media.setAnPath(FileUtil.path + File.pathSeparator + fileName);
DaoManager.update(media);
ShadowFactory.notifyUpdate(media);
}
});
}
break;
}
}
这个方法主要管理的是柜子端界面上宣传展示的部分(主要是宣传图)。media是自定义的一个媒体文件对象。if-continue部分主要说明在media文件不存在的时候,则不报错。在media文件存在时,如果这个媒体文件没有被下载到本机立即发起网络请求,下载这个文件到本机,完成后执行回调。使用
media.setDownloaded(true);
media.setAnPath(FileUtil.path + File.pathSeparator + fileName);
DaoManager.update(media);
ShadowFactory.notifyUpdate(media);
更新影子中,当前media的downloaded标志位,同时更新文件存放位置url;更新数据库;发送到后台,并通知前端媒体组件,更新媒体列表