web-dev-qa-db-ja.com

Androidアクティビティの情報をバックグラウンドサービスから更新するにはどうすればよいですか?

シンプルなAndroid情報のActivityListを持つアプリケーションを作成しようとしています。アプリケーションが起動すると、常にデータを計算する(変更される)サービスを開始する予定です。 ActivityListを、サービスがアプリの存続期間中に計算しているデータと同期させたい。

サービスをリッスンするようにアクティビティを設定するにはどうすればよいですか?これはこの問題に取り組む最良の方法ですか?

たとえば、株価のリストを想像すると、データは定期的に変更され、データを絶えず計算/フェッチしている(私の場合)サービスと同期する必要があります。

前もって感謝します

40
rhinds

サービスをリッスンするようにアクティビティを設定するにはどうすればよいですか?これはこの問題に取り組む最良の方法ですか?

私が見るように、あなたには3つの主要な選択肢があります。

  1. ポーリング。 Activityは定期的にServiceに最新のデータを要求します。私見、このオプションはうんざりですが、それは確かに可能です。

  2. コールバック。 jaxの回答に従って、ActivityServiceにコールバックオブジェクト( "observer")を登録します。 Serviceは、データが変更されるとコールバックでメソッドを呼び出し、UIを更新します。 Servicehere での使用例を見ることができます。

  3. ブロードキャストIntentsServiceは、データ変更時にsendBroadcast()を介してIntentをブロードキャストします。 ActivityregisterReceiver()を使用してBroadcastReceiverを登録し、そのBroadcastReceiverに着信ブロードキャストが通知されます。これによりActivityがトリガーされ、Serviceから最新のデータが読み込まれるか、ブロードキャストIntentのエクストラから最新のデータが取得される可能性があります。 Servicehere でこの手法を使用する例を見ることができます。

95
CommonsWare

これはObserverパターンの良い候補のように思えます。基本的に、アクティビティ(The Observer)はバックグラウンドサービス(The Observable)に登録され、アクティビティからデータをプッシュまたはプルできます。この場合のオブザーバーはアクティビティになり、オブザーバブルはサービスになります。

デザインパターンについて何も知らない場合、「Head First Design Patterns」を購入すると、読みやすく、優れた情報が満載です。

PS:私は今それを読んでいます。

4
jax

どのようなライブラリでも、EventBusを使用した簡単なアプローチについて誰も言及しなかったのはなぜでしょうか。もちろん、これはRXを使用していない場合です。私の個人的なお気に入りは、GreenRobotによるEventBusです。 https://github.com/greenrobot/EventBus

ほんの数行のコードで、インターフェースはありません。イベントを起動して、どこでも好きな場所で聞いてください。分離されており、スレッドセーフであり、アプリをクラッシュさせません。

2
miroslavign

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);
  }
}
1
Arun kumar

リストの変更を計算するバックグラウンドスレッドが実行されます。このスレッドには、リストが更新されたことをGUIに通知する機能が必要になりました。

何らかの ArrayAdapter を使用して、データをListViewに取得できます。 ArrayAdapterには adpater.notifyDataSetChanged() というメソッドがあり、このメソッドを呼び出すたびに、アダプターは対応するデータが変更されたことを確認し、次の可能性でリストビューに更新するよう通知します。

0
Janusz