簡體   English   中英

如何從后台服務更新Android活動中的信息

[英]How can I update information in an Android Activity from a background Service

我正在嘗試創建一個具有ActivityList信息的簡單Android應用程序,當應用程序啟動時,我計划啟動一個將不斷計算數據的服務(它將會改變),我希望ActivityList與之同步服務計算應用程序生命周期的數據。

如何設置我的Activity以收聽服務? 這是解決此問題的最佳方法嗎?

例如,如果您想象一個股票價格列表 - 數據將定期更改,並且需要與(在我的情況下)不斷計算/獲取數據的服務同步。

提前致謝

如何設置我的Activity以收聽服務? 這是解決此問題的最佳方法嗎?

你有三個主要選擇,我認為:

  1. 輪詢。 Activity定期向Service詢問最新數據。 恕我直言,這個選項很糟糕,但它肯定是可能的。

  2. 回調。 根據jax的回答, ActivityService注冊了一個回調對象(“觀察者”)。 當數據發生更改時, Service在回調上調用方法,從而更新UI。 您可以在此處查看使用Service的示例。

  3. 廣播Intents Service通過sendBroadcast()在數據更改時廣播Intent Activity使用registerReceiver()注冊BroadcastReceiver ,並向BroadcastReceiver通知傳入的廣播。 這會觸發ActivityService加載最新數據,或者可能只是為了從廣播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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM