如何从后台服务更新 Android Activity 中的信息

发布于 2024-08-25 18:38:13 字数 236 浏览 8 评论 0原文

我正在尝试创建一个简单的Android应用程序,它有一个ActivityList信息,当应用程序启动时,我计划启动一个服务,它将不断计算数据(它会改变),并且我希望ActivityList与服务在应用程序生命周期内计算的数据。

如何将我的活动设置为监听服务?这是解决这个问题的最佳方法吗?

例如,如果您想象一个股票价格列表 - 数据将定期更改,并且需要与不断计算/获取数据的(在我的例子中)服务同步。

提前致谢

I am trying to create a simple Android application that has a ActivityList of information, when the application starts, I plan to start a Service that will be constantly calculating the data (it will be changing) and I want the ActivityList to be in sync with the data that the service is calculating for the life of the app.

How can I set up my Activity to be listening to the Service? Is this the best way to approach this problem?

For example, if you imagine a list of stock prices - the data would be being changed regularly and need to be in sync with the (in my case) Service that is calculating/fetching the data constantly.

Thanks in advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

山人契 2024-09-01 18:38:14

您将运行一个后台线程来计算列表中的更改。该线程现在需要能够通知 GUI 列表已更新。

您可以使用某种 ArrayAdapter 来获取数据到ListView中。 ArrayAdapter 有一个名为 adpater 的方法。每次调用此方法时,适配器都会看到相应的数据已更改,然后通知列表视图应该在下一次可能的情况下更新。

You will have a background thread running that calculates the changes in the list. This thread now needs a possibility to notify the GUI that the list was updated.

You can use some kind of ArrayAdapter to get the data into the ListView. The ArrayAdapter has a method called adpater.notifyDataSetChanged() every time you call this method the adapter will see that the corresponding data has changed and then notify the listview that it should update at the next possibility.

苹果你个爱泡泡 2024-09-01 18:38:13

我如何将我的活动设置为
听服务?这是吗
解决这个问题的最佳方法?

在我看来,您有三个主要选择:

  1. 投票。 Activity 定期向Service 请求最新数据。恕我直言,这个选项很糟糕,但它肯定是可能的。

  2. 回调。根据 jax 的回答,ActivityService 注册一个回调对象(“观察者”)。当数据更改时,Service 会调用回调方法,从而更新 UI。您可以查看将其与 Service 结合使用的示例

  3. 广播意图Service 在数据更改时通过 sendBroadcast() 广播 IntentActivity 使用 registerReceiver() 注册一个 BroadcastReceiver,并且 BroadcastReceiver 会收到传入广播的通知。这会触发ActivityService加载最新数据,或者可能只是从广播Intent中的额外内容中获取最新数据。您可以查看通过 Service 使用该技术的示例

How can I set up my Activity to be
listening to the Service? Is this the
best way to approach this problem?

You have three major options, as I see it:

  1. Polling. The Activity periodically asks the Service for the latest data. IMHO, this option sucks, but it's certainly possible.

  2. Callbacks. Per jax's answer, the Activity registers a callback object ("observer") with the Service. The Service invokes a method on the callback when the data changes, which in turn updates the UI. You can see an example of using that with a Service here.

  3. Broadcast Intents. The Service broadcasts an Intent via sendBroadcast() on a data change. The Activity registers a BroadcastReceiver using registerReceiver(), and that BroadcastReceiver is notified of an incoming broadcast. This triggers the Activity to load the latest data from the Service, or possibly just to get the latest data out of extras in the broadcast Intent. You can see an example of using that technique with a Service here.

爱人如己 2024-09-01 18:38:13

这听起来像是观察者模式的一个很好的候选者。基本上,您的活动(观察者)将向后台服务(可观察的)注册自身,并且您可以从活动中推送或提取数据。在这种情况下,您的观察者将是您的活动,而可观察者将是您的服务。

如果您对设计模式一无所知,请购买《Head First Design Patterns》,它很容易阅读,并且充满了丰富的信息。

PS:我现在正在读。

This sound like a good candidate for the Observer Pattern. Basically your activity (The Observer) will register itself with the background service (The Observable) and you can push or pull data from your Activity. Your Observer in this case will be your Activity and the Observable will be your Service.

If you know nothing about Design Patterns buy "Head First Design Patterns", it is easy to read and is full of great information.

PS: I am reading it now.

弥繁 2024-09-01 18:38:13

我真的非常想知道为什么没有人提到任何库使用 EventBus 的简单方法。当然这是在您不使用 RX 的情况下。
我个人最喜欢的是 GreenRobot 的 EventBus。
https://github.com/greenrobot/EventBus

只需几行代码,接口。触发一个事件,并在任何您想要的地方监听它。它是解耦的,线程安全的,并且不会使您的应用程序崩溃。

I am really, really wondering why no one mentioned a simple approach using an EventBus by whatever library. This is of course if you are not using RX.
My personal favorite is EventBus by GreenRobot.
https://github.com/greenrobot/EventBus

With just a couple of lines of code, and no interfaces. Fire an event, and listen for it wherever you want. It is decoupled, it is thread safe, and it will not crash your app.

柏林苍穹下 2024-09-01 18:38:13

您需要使用bindService()将活动与正在运行的服务绑定并与其通信。

public class BindingActivity extends Activity {
YourService mService;
boolean mBound = false;

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

@Override
protected void onStart() {
    super.onStart();
    // Bind to Your Service
    Intent intent = new Intent(this, YourService.class);
    bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}

@Override
protected void onStop() {
    super.onStop();
    // Unbind from the service
    if (mBound) {
        unbindService(mConnection);
        mBound = false;
    }
}

/** Called when a button is clicked (the button in the layout file attaches to
  * this method with the android:onClick attribute) */
public void onButtonClick(View v) {
    if (mBound) {
        // Call a method from your Service.
        // However, if this call were something that might hang, then this request should
        // occur in a separate thread to avoid slowing down the activity performance.
        int num = mService.getRandomNumber();
        Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
    }
}

/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() {

    @Override
    public void onServiceConnected(ComponentName className,
            IBinder service) {
        // We've bound to the running Service, cast the IBinder and get instance
        LocalBinder binder = (LocalBinder) service;
        mService = binder.getService();
        mBound = true;
    }

    @Override
    public void onServiceDisconnected(ComponentName arg0) {
        mBound = false;
    }
 };
}

您的服务如下:

public class LocalService extends Service {
    // Binder given to clients
   private final IBinder mBinder = new LocalBinder();
   // Random number generator
   private final Random mGenerator = new Random();

/**
 * Class used for the client Binder.  Because we know this service always
 * runs in the same process as its clients, we don't need to deal with IPC.
 */
public class LocalBinder extends Binder {
    LocalService getService() {
        // Return this instance of LocalService so clients can call public methods
        return LocalService.this;
    }
}

@Override
public IBinder onBind(Intent intent) {
    return mBinder;
}

/** method for clients */
public int getRandomNumber() {
  return mGenerator.nextInt(100);
  }
}

You need to use bindService() to bind the activity with running service and communicate with it.

public class BindingActivity extends Activity {
YourService mService;
boolean mBound = false;

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

@Override
protected void onStart() {
    super.onStart();
    // Bind to Your Service
    Intent intent = new Intent(this, YourService.class);
    bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}

@Override
protected void onStop() {
    super.onStop();
    // Unbind from the service
    if (mBound) {
        unbindService(mConnection);
        mBound = false;
    }
}

/** Called when a button is clicked (the button in the layout file attaches to
  * this method with the android:onClick attribute) */
public void onButtonClick(View v) {
    if (mBound) {
        // Call a method from your Service.
        // However, if this call were something that might hang, then this request should
        // occur in a separate thread to avoid slowing down the activity performance.
        int num = mService.getRandomNumber();
        Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show();
    }
}

/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() {

    @Override
    public void onServiceConnected(ComponentName className,
            IBinder service) {
        // We've bound to the running Service, cast the IBinder and get instance
        LocalBinder binder = (LocalBinder) service;
        mService = binder.getService();
        mBound = true;
    }

    @Override
    public void onServiceDisconnected(ComponentName arg0) {
        mBound = false;
    }
 };
}

and your service like:

public class LocalService extends Service {
    // Binder given to clients
   private final IBinder mBinder = new LocalBinder();
   // Random number generator
   private final Random mGenerator = new Random();

/**
 * Class used for the client Binder.  Because we know this service always
 * runs in the same process as its clients, we don't need to deal with IPC.
 */
public class LocalBinder extends Binder {
    LocalService getService() {
        // Return this instance of LocalService so clients can call public methods
        return LocalService.this;
    }
}

@Override
public IBinder onBind(Intent intent) {
    return mBinder;
}

/** method for clients */
public int getRandomNumber() {
  return mGenerator.nextInt(100);
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文