Android 从服务到UI层的同步消息
广播意图的顺序是否得到保证?就是说,如果我这样做了,Android 从服务到UI层的同步消息,android,android-intent,android-service,Android,Android Intent,Android Service,广播意图的顺序是否得到保证?就是说,如果我这样做了, sendBroadcast(intent1); sendBroadcast(intent2); 接收器是否保证在intent2之前获得intent1?我怀疑答案是否定的,但在这种情况下,我不太确定如何解决我的问题 我正在尝试为我的应用程序创建一个“忙碌”指示器,当设备在网络上通话时显示忙碌,然后在网络通信结束时消失。所有网络通信都发生在意图服务中 我的尝试是在服务中开始网络通信时发送一个忙碌的开始意图,在网络通信结束时发送一个忙碌的停止。这
sendBroadcast(intent1);
sendBroadcast(intent2);
接收器是否保证在intent2之前获得intent1?我怀疑答案是否定的,但在这种情况下,我不太确定如何解决我的问题
我正在尝试为我的应用程序创建一个“忙碌”指示器,当设备在网络上通话时显示忙碌,然后在网络通信结束时消失。所有网络通信都发生在意图服务中
我的尝试是在服务中开始网络通信时发送一个忙碌的开始意图,在网络通信结束时发送一个忙碌的停止。这似乎大部分是有效的,但我偶尔会发现我收到的停止和开始信息的顺序
有没有更好的办法来解决这个问题
我正在考虑为每个忙碌的意图添加一个ID,这样它们就可以配对了。这样,如果我收到一个开始,而我已经收到一个停止,我可以忽略它。或者,更简单地说,在每个广播中添加一个整数序列号。如果我接收到的广播当前意图的顺序小于上次接收到的意图的顺序,请忽略它。您是否考虑过使用
处理程序
对象从IntentService
中的后台线程进行通信?与broadcastReceiver
方法相比,处理程序的优势在于,处理程序使用消息队列对消息对象进行排序
(我假设您的服务与应用程序的主线程处于相同的过程中)。回答我自己的问题 意图的至少一个可行替代方案是通过应用程序类执行消息传递,即
public class MyApplication extends Application {
public interface MyListener {
void onEvent();
}
private Set<MyListener> listeners = new HashSet<Listener>();
public void addListener(MyListener l) {
listeners.add(l);
}
public void removeListener(MyListener l) {
listeners.remove(l);
}
public void sendEvent() {
for (MyListener l: listeners) { l.onEvent(); }
}
}
为您服务
((MyApplication)getApplication()).sendEvent();
这在不使用意图或静态变量的情况下提供同步消息传递。我正在尝试从意图服务到UI线程进行通信。是的。处理程序应该这样做。或者我遗漏了什么?在这种情况下,您需要在活动中构造处理程序,并为服务提供对它的引用。如何做到这一点?简单的答案是将其存储在某个静态变量中。您可以查看谷歌的应用内计费示例代码。他们的代码有点过度设计,但基本上他们的服务调用helper对象上的静态方法,该对象最终持有对Handler对象的静态引用。或者,如果您不喜欢静态(我不喜欢),您可以在应用程序的应用程序对象中存储对它的引用,并让服务从中检索它。如果服务得到一个空处理程序,它将跳过消息传递。我不能接受使用静态字段是组件间消息传递的最佳实践,不管它来自google示例代码。正如您在这里介绍的,看起来它从服务线程直接调用活动的主UI线程。这是一个禁忌。我真的认为如果你想从一个线程调用另一个线程,你需要一个Handler对象。你是对的,它确实需要。假设如果活动在
onEvent()
中修改UI线程,则应使用runOnUIThread()
进行修改。如果我们愿意,回调框架可以隐藏这一点,但我宁愿让UI线程来决定是否需要这一额外步骤。你提到的一件好事是,对于那些希望在自己的应用程序中使用你的代码示例的人来说。我不是在这里向大家指出android应用程序开发的每一个细微差别。理解不能从非UI线程更新UI层次结构是一个非常基本的概念。我已经花了相当长的时间回到这里,为我自己的问题写了一个长而详细的答案。不客气。如果你有问题,我建议你投票删除这个问题。
((MyApplication)getApplication()).sendEvent();