[英]How can I update information in an Android Activity from a background Service
我正在嘗試創建一個具有ActivityList信息的簡單Android應用程序,當應用程序啟動時,我計划啟動一個將不斷計算數據的服務(它將會改變),我希望ActivityList與之同步服務計算應用程序生命周期的數據。
如何設置我的Activity以收聽服務? 這是解決此問題的最佳方法嗎?
例如,如果您想象一個股票價格列表 - 數據將定期更改,並且需要與(在我的情況下)不斷計算/獲取數據的服務同步。
提前致謝
如何設置我的Activity以收聽服務? 這是解決此問題的最佳方法嗎?
你有三個主要選擇,我認為:
輪詢。 Activity
定期向Service
詢問最新數據。 恕我直言,這個選項很糟糕,但它肯定是可能的。
回調。 根據jax的回答, Activity
在Service
注冊了一個回調對象(“觀察者”)。 當數據發生更改時, Service
在回調上調用方法,從而更新UI。 您可以在此處查看使用Service
的示例。
廣播Intents
。 Service
通過sendBroadcast()
在數據更改時廣播Intent
。 Activity
使用registerReceiver()
注冊BroadcastReceiver
,並向BroadcastReceiver
通知傳入的廣播。 這會觸發Activity
從Service
加載最新數據,或者可能只是為了從廣播Intent
的額外內容中獲取最新數據。 您可以在此處查看將此技術與Service
一起使用的示例。
這聽起來像觀察者模式的一個很好的候選人。 基本上您的活動(The Observer)將使用后台服務(The Observable)注冊自己,您可以從Activity中推送或提取數據。 在這種情況下,您的觀察者將是您的活動,而Observable將是您的服務。
如果您對Design Patterns一無所知,請購買“Head First Design Patterns”,它易於閱讀並且充滿了很多信息。
PS:我現在正在讀它。
我真的非常想知道為什么沒有人提到使用任何庫的EventBus的簡單方法。 這當然是你不使用RX。 我個人最喜歡的是GreenRobot的EventBus。 https://github.com/greenrobot/EventBus
只有幾行代碼,沒有接口。 發射一個事件,隨時隨地傾聽。 它是分離的,它是線程安全的,它不會崩潰您的應用程序。
您需要使用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);
}
}
您將運行后台線程來計算列表中的更改。 該線程現在需要通知GUI該列表已更新。
您可以使用某種ArrayAdapter將數據導入ListView。 ArrayAdapter有一個名為adpater.notifyDataSetChanged()的方法,每次調用此方法時,適配器將看到相應的數據已更改,然后通知列表視圖它應該在下一種可能性時更新。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.