Java Android:根据服务中后台线程的对象值更新UI
我目前正在开发一款Android应用程序,其中包含以下活动:Java Android:根据服务中后台线程的对象值更新UI,java,android,multithreading,Java,Android,Multithreading,我目前正在开发一款Android应用程序,其中包含以下活动: 主要活动 更新活动 此外,它还包含一个完全独立的包,其中存在以下类: SyncService:正如名称所示,它是一种服务。更具体地说是绑定服务 SyncServiceManager:绑定到服务的单例对象 SyncTask:仅包含服务需要执行的逻辑。因此,服务是与之交互的唯一对象 两个接口使我的经理能够与服务交互。和2个界面,仅用于我的应用程序的观察者模式。服务是应该通知经理、syncTask和updateActivity执行某些
- 主要活动李>
- 更新活动
- SyncService:正如名称所示,它是一种服务。更具体地说是绑定服务李>
- SyncServiceManager:绑定到服务的单例对象
- SyncTask:仅包含服务需要执行的逻辑。因此,服务是与之交互的唯一对象李>
- 两个接口使我的经理能够与服务交互。和2个界面,仅用于我的应用程序的观察者模式。服务是应该通知经理、syncTask和updateActivity执行某些操作的主体
public enum ServiceState {
RESETTING,
CONFIGURING,
SYNCHRONIZING,
IDLE
}
private Vector<IObserver> observers = new Vector<IObserver>();
private IBinder syncBinder = new SyncServiceBinder();
private ServiceState serviceState;
@Nullable
@Override
public IBinder onBind(Intent intent) {
return syncServiceBinder;
}
private final IBinder syncServiceBinder = new SyncServiceBinder();
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Thread th = new Thread(new Runnable() {
@Override
public void run() {
//Modifying the service state and starting the sync depending on the state.
startSync();
}
});
th.start();
return START_REDELIVER_INTENT;
}
private void startSync() {
notifyObservers(serviceState);
}
@Override
public void registerObserver(IObserver iObserver) {
observers.add(iObserver);
}
@Override
public void unregisterObserver(IObserver iObserver) {
observers.remove(iObserver);
}
@Override
public void notifyObservers(SyncService.ServiceState serviceState) {
for (IObserver observer : observers) {
observer.update();
}
}
}
我还考虑过使用activity类附带的runOnUiThread函数,但它启动得太晚了。在updateactivity中创建一个新的处理程序,并创建一个runnable,这应该允许我向处理程序发送消息
你们有什么想法/建议吗
提前感谢,
迈克尔在这种情况下,广播听众将是最好的,也被推荐。只需在activity中创建广播侦听器,它将更新UI,在onStart中注册,并在onStop中注销。我认为您的逻辑太复杂了。没有必要把这一切搞得一团糟。 你只需要主要的活动类和服务,你就可以得到更多。您甚至不需要绑定服务 由于活动和服务在同一个进程中运行,因此在它们之间共享状态的一个好方法是静态变量。因此,将服务状态设为静态,并设置一个getter,以便活动可以访问服务的状态 当需要更新UI时,您可以向活动发送广播,在onStart中注册,在onStop中注册(根据需要,onPause和onResume也可以工作) 尽管我认为比广播更简单的方法是使用事件总线,比如otto。 只需创建一个提供总线的单例类,进入服务并将事件发布到总线上(参见如何从后台发布到主线程的示例,这非常简单)。在活动中,按照我前面所说的方法注册和注销,并设置@susbuide事件 一些代码示例: 从服务发布更新:
EventBusProvider.getInstance().postToMainThread(new SomeEventOrAnyClassObject());
注册和注销活动以侦听总线:
@Override
public void onStart(){
super.onStart();
EventBusProvider.getInstance().register(this);
@Override
public void onStop(){
super.onStop();
EventBusProvider.getInstance().unregister(this);
}
订阅以接收更新
@Subscribe
public void loginResponse(Data someinstance){
//Here you could read the update directly from the someinstance
//or check the service static variable
SyncService.getStatus()
}
这真的很容易。希望它有助于创建BroadCastReceiver,并通过服务Broadcast intent在您的活动中注册它。根据
onReceive
中的数据,将您的活动更新为旁注:如果您在onStart
中注册,您希望在onStop
中注销。如果您在onResume
中注销,请在onPause
中注册,否则您可能会遇到一些奇怪的生命周期问题(尤其是片段
s)。@AlexTownsend您预计会发生什么样的奇怪生命周期问题?我只是没有看到任何与此相关的内容。@InvertedNetwork我们在生产中看到了一些问题,在这些问题中,围绕片段的配置更改会导致本应取消注册的接收器试图触发。不是很常见,但最好是安全的,只需在正确镜像的生命周期回调中注册/注销即可:)好吧,我想说这取决于您希望何时注销侦听器。但不依赖OnStop更安全,因为有时系统不会调用它。因此,最后一个操作是OnStart&OnPause或OnResume&OnPause。如果您正确理解了何时调用这些方法,那么这不应该是一个问题。它部分地解决了这个问题。我现在面临的唯一问题是,我需要确保BroadcastListener立即接收到广播的意图。因为现在有3秒左右的延迟。这会导致在侦听器响应广播时更新活动已经关闭的情况。
@Subscribe
public void loginResponse(Data someinstance){
//Here you could read the update directly from the someinstance
//or check the service static variable
SyncService.getStatus()
}