简体   繁体   English

Android:根据服务中后台线程中对象的值更新UI

[英]Android: update UI depending on value of object from background thread in service

I am currently developing an Android app which contains the following activities: 我目前正在开发一个Android应用,其中包含以下活动:

  • MainActivity; 主要活动;
  • UpdateActivity. UpdateActivity。

Besides that it also contains a completely separate package in which exists the following classes: 除此之外,它还包含一个完全独立的包,其中包含以下类:

  • SyncService: which is, as the name already indicates, a service. SyncService:顾名思义,它是一项服务。 To be more specific a bound service; 更具体地说,是绑定服务;
  • SyncServiceManager: a singleton object which binds to the service. SyncServiceManager:绑定到服务的单例对象。
  • SyncTask: only containing the logic that the service needs to do. SyncTask:仅包含服务需要执行的逻辑。 So the service is the only object that interact with it; 因此,服务是与之交互的唯一对象。
  • A couple of interfaces to make it possible for my manager to interact with the service. 几个接口使我的经理可以与服务进行交互。 And 2 interfaces just to use the Observer Pattern for my app. 还有2个界面,仅用于我的应用程序的观察者模式。 The Service is the subject which is supposed to notify the manager, the syncTask and the updateActivity to do something. 服务是应该通知管理器,syncTask和updateActivity做某事的主题。

The problem I am facing is that I want to modify the UI of my updateActivity depending on an enum that changes as the service needs to do his job. 我面临的问题是,我想根据服务需要完成工作的枚举来修改updateActivity的UI。 Which is notifying the syncTask to do the requested job (Configuring, Resetting or Syncing the application database with the data of a webservice). 它通知syncTask进行请求的工作(使用Web服务的数据配置,重置或同步应用程序数据库)。

However since I want to make the service do his thing in the background I'm using a new thread object in which it can do thing I want it to do. 但是,由于我想让服务在后台执行他的任务,所以我使用了一个新的线程对象,在其中可以执行我想执行的操作。 This is all kind of working the way it should, except for the fact that I can modify the UI in the update activity because the UI can only be edited from the UI Thread. 这是应该进行的所有工作,除了我可以在更新活动中修改UI的事实之外,因为只能从UI线程中编辑UI。 I've already found a very promising link on the forum, but I just can't figure out if it really is the thing I need and/or how to implement it. 我已经在论坛上找到一个非常有前途的链接,但是我无法弄清楚它是否真的是我需要的东西和/或如何实现它。 android: update UI from another thread in another class android:从另一个类中的另一个线程更新UI

This is my code. 这是我的代码。 The Service: 服务:

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

The update activity: 更新活动:

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
}

} }

I've also thought of using the runOnUiThread function which comes with the activity class, but it just gets fired way too late. 我还考虑过使用活动类附带的runOnUiThread函数,但是它被触发得太晚了。 The same thing with creating a new handler within the updateactivity and create a runnable which should allow me to send a message to the handler. 在updateactivity中创建一个新的处理程序并创建一个runnable,这应该允许我向处理程序发送消息。

You guys have any thoughts/suggestions? 你们有什么想法/建议吗?

Thanks in Advance, 提前致谢,

Michael 迈克尔

Broadcast Listener would be best in this case and also recommended. 在这种情况下,Broadcast Listener最好,并且也建议使用。 Just create Broadcast listener in activity which will update the UI, register it in onStart and unregister in onStop. 只需在活动中创建广播侦听器即可更新UI,在onStart中注册它,然后在onStop中注销。

I think you really overcomplicated your logic. 我认为您确实使逻辑过于复杂。 There is no necessecity for all that mess. 所有这些混乱都没有必要。 You only need the main activity class and the service, and you got more than enought. 您只需要主要活动类和服务,您就获得了足够的收益。 You dont even need to bind the service. 您甚至不需要绑定服务。

As the Activity and the service run in the same process, a good way to share state between them are static variables. 由于Activity和服务在同一进程中运行,因此在它们之间共享状态的一种好方法是静态变量。 So make service state static and set up a getter so the activity can access the state of the service. 因此,使服务状态为静态并设置吸气剂,以便活动可以访问服务状态。

When the UI needs to be updated you can send a broadcast to the activity, registering in onStart and onregistering in onStop ( onPause and onResume could also work, depending on your needs). 当需要更新UI时,您可以向活动发送广播,可以在onStart上注册,也可以在onStop上注册on(根据需要,onPause和onResume也可以工作)。

Though i think a much easier approach than a Broadcast its just using a event bus, like otto. 尽管我认为比广播更简单的方法是仅使用事件总线,例如otto。 Just create a singleton class providing the bus, get in the service and post the event to the bus (see examples on how to post to main thread from backgroun, its pretty easy). 只需创建一个提供总线的单例类,进入服务并将事件发布到总线(请参阅有关如何从backgroun向主线程发布的示例,这非常简单)。 In the activity register and unregister the same way as i said before, and set up a @susbribe event. 在活动中以与我之前说过的相同方式注册和注销,并设置一个@susbribe事件。

Some code samples: 一些代码示例:

Posting the update from service: 从服务发布更新:

EventBusProvider.getInstance().postToMainThread(new SomeEventOrAnyClassObject());

Registering and unregistering the activity to listen to the bus: 注册和注销活动以监听总线:

  @Override
public void onStart(){
    super.onStart();
    EventBusProvider.getInstance().register(this);

 @Override
public void onStop(){
    super.onStop();
    EventBusProvider.getInstance().unregister(this);
}

Subscribing to receive the update 订阅以接收更新

 @Subscribe
public void loginResponse(Data someinstance){
 //Here you could read the update directly from the someinstance
//or check the service static variable
 SyncService.getStatus()
}

It's really that easy. 真的很容易。 hope its helps 希望能有所帮助

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM