2016-02-29 35 views
1

我目前正在开发Android应用程序包含以下活动:安卓:根据从后台线程对象的值更新UI服务

  • MainActivity;
  • UpdateActivity。

除此之外它还包含一个完全独立的包装,其中存在以下类:

  • SyncService:其是,正如名称已经表明,一个服务。更具体一个绑定服务;
  • SyncServiceManager:其结合于该服务的单独的对象。
  • SyncTask:只包含服务需要执行的逻辑。所以服务是唯一与之交互的对象;
  • 一对夫妇的接口,有可能使我的经理与服务进行交互。而2个接口只是为我的应用使用观察者模式。服务是应该通知经理,syncTask和updateActivity做某事的主题。

我面临的问题是,我想修改我的updateActivity的UI,取决于服务需要执行其工作时更改的枚举。通知syncTask执行所请求的作业(使用Web服务的数据配置,重置或同步应用程序数据库)。

然而,因为我想使服务做他的事情的背景我用一个新的线程对象,它可以做我想做的事情的事情。 除了事实上我可以修改更新活动中的用户界面,因为只能从UI线程编辑用户界面,所以这是所有类型的工作方式。 我已经在论坛上发现了一个非常有前途的链接,但我无法弄清楚它是否真的是我需要的和/或如何实现的。 android: update UI from another thread in another class

这是我的代码。 的服务:

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(); 
    } 
} 

更新活动:

public class UpdateActivity extends Activity implements IObserver { 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.update_activity); 
} 

@Override 
public void update() { 
    //Modify UI from here depeding on the serviceState 
} 

}

我也想过用其自带的活动类的runOnUiThread的功能,但它只是被炒鱿鱼的方式太晚了。在updateactivity中创建一个新的处理程序并创建一个允许我向处理程序发送消息的runnable也是如此。

你们有什么想法/建议?

由于事先

迈克尔

+0

创建BroadCastReceiver并将其注册到您的活动中,从服务Broad Cast的意图。根据'onReceive'中的数据更新您的活动 – Pragnani

回答

1

广播监听器将是最好在这种情况下,并建议。只需在将更新UI的活动中创建Broadcast listener,将其注册到onStart并在onStop中取消注册。

+0

附注:如果您在'onStart'中注册,则想要在'onStop'中取消注册。如果你在'onPause'中注销,你可以在'onResume'注册,否则你可能会遇到一些奇怪的生命周期问题(尤其是使用'Fragment')。 –

+0

@AlexTownsend您期望发生什么样的奇怪生命周期问题?我只是没有看到任何与此有关的。 – InvertedNetwork

+0

@InvertedNetwork我们看到生产中出现了一些问题,这些问题围绕碎片进行了配置更改,其中应该注销Receiver的Receiver会尝试启动。不是很常见,但最好是安全的,只需在正确镜像的生命周期回调中注册/取消注册:) –

0

我觉得你真的过于复杂的逻辑问题。所有这一切都没有必要。 你只需要主要的活动类和服务,而且你已经足够了。你甚至不需要绑定服务。

由于Activity和服务在同一进程中运行,所以在它们之间共享状态的好方法是静态变量。因此,请将服务状态设置为静态并设置一个getter,以便活动可以访问服务的状态。

当需要更新用户界面时,您可以向该活动发送广播,在onStart中注册并注册onStop(onPause和onResume也可以工作,具体取决于您的需要)。

虽然我觉得比广播更简单的方法就是使用事件总线,比如otto。 只需创建一个提供公共汽车的单身人士课程,获取服务并将事件发布到公共汽车上(请参阅关于如何从背景发布到主线程的示例,它非常简单)。在活动注册和注销方式与我之前说过的一样,并设置一个@susbribe事件。

一些代码示例:

发布的服务更新:

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() 
} 

真的很简单。希望它的帮助