Java 如何从后台服务更新 Android Activity 中的信息
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2468874/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I update information in an Android Activity from a background Service
提问by rhinds
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.
我正在尝试创建一个具有 ActivityList 信息的简单 Android 应用程序,当应用程序启动时,我计划启动一个将不断计算数据(它会发生变化)的服务,并且我希望 ActivityList 与服务为应用程序的生命周期计算的数据。
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
提前致谢
采纳答案by CommonsWare
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:
在我看来,您有三个主要选择:
Polling. The
Activity
periodically asks theService
for the latest data. IMHO, this option sucks, but it's certainly possible.Callbacks. Per jax's answer, the
Activity
registers a callback object ("observer") with theService
. TheService
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 aService
here.Broadcast
Intents
. TheService
broadcasts anIntent
viasendBroadcast()
on a data change. TheActivity
registers aBroadcastReceiver
usingregisterReceiver()
, and thatBroadcastReceiver
is notified of an incoming broadcast. This triggers theActivity
to load the latest data from theService
, or possibly just to get the latest data out of extras in the broadcastIntent
. You can see an example of using that technique with aService
here.
轮询。将
Activity
定期询问Service
最新数据。恕我直言,这个选项很糟糕,但这当然是可能的。回调。根据 jax 的回答,它
Activity
使用Service
. 在Service
上调用回调方法在数据改变时,这反过来又更新UI。您可以Service
在此处查看使用它的示例。广播
Intents
。该Service
播放器Intent
通过sendBroadcast()
对数据的变化。的Activity
一个寄存器BroadcastReceiver
使用registerReceiver()
,而且BroadcastReceiver
被通知传入的广播。这会触发从Activity
加载最新数据Service
,或者可能只是从广播中的附加数据中获取最新数据Intent
。您可以Service
在此处查看使用该技术的示例。
回答by jax
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.
这听起来像是观察者模式的一个很好的候选者。基本上你的活动(观察者)会向后台服务(观察者)注册自己,你可以从你的活动中推送或拉取数据。在这种情况下,您的观察者将是您的 Activity,而 Observable 将是您的服务。
If you know nothing about Design Patterns buy "Head First Design Patterns", it is easy to read and is full of great information.
如果您对设计模式一无所知,请购买“Head First Design Patterns”,它很容易阅读并且包含大量信息。
PS: I am reading it now.
PS:我现在正在阅读。
回答by Janusz
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.
您将运行一个后台线程来计算列表中的更改。该线程现在需要通知 GUI 列表已更新。
You can use some kind of ArrayAdapterto 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.
您可以使用某种ArrayAdapter将数据放入 ListView。ArrayAdapter 有一个名为adpater.notifyDataSetChanged()的方法,每次调用此方法时,适配器都会看到相应的数据已更改,然后通知列表视图它应该在下一次更新。
回答by Arun kumar
You need to use bindService() to bind the activity with running service and communicate with it.
您需要使用 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;
}
};
}
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);
}
}
回答by miroslavign
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
我真的非常想知道为什么没有人提到任何库都使用 EventBus 的简单方法。这当然是如果您不使用 RX。我个人最喜欢的是 GreenRobot 的 EventBus。 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.
只需几行代码,没有接口。触发一个事件,并在任何你想要的地方收听它。它是解耦的,它是线程安全的,并且不会使您的应用程序崩溃。