백그라운드 서비스에서 Android 활동의 정보를 업데이트하려면 어떻게 해야 하나요?
-
20-09-2019 - |
문제
정보 ActivityList가 있는 간단한 Android 애플리케이션을 만들려고 합니다. 애플리케이션이 시작되면 지속적으로 데이터를 계산하는 서비스를 시작할 계획이며(변경될 예정임) ActivityList가 동기화되기를 원합니다. 서비스가 앱 수명 동안 계산하는 데이터입니다.
서비스를 수신하도록 내 활동을 어떻게 설정합니까?이것이 이 문제에 접근하는 가장 좋은 방법입니까?
예를 들어, 주가 목록을 상상한다면 데이터는 정기적으로 변경되며 (내 경우에는) 데이터를 지속적으로 계산/가져오는 서비스와 동기화되어야 합니다.
미리 감사드립니다
해결책
서비스를 듣기 위해 내 활동을 어떻게 설정할 수 있습니까? 이것이이 문제에 접근하는 가장 좋은 방법입니까?
내가 볼 수 있듯이 세 가지 주요 옵션이 있습니다.
투표. 그만큼
Activity
주기적으로 묻습니다Service
최신 데이터의 경우. IMHO,이 옵션은 짜증나지만 확실히 가능합니다.콜백. Jax의 대답에 따라
Activity
콜백 개체 ( "관찰자")를Service
. 그만큼Service
데이터가 변경 될 때 콜백에서 메소드를 호출하여 UI가 업데이트됩니다. 당신은 그것을 사용하는 예를 볼 수 있습니다.Service
여기.방송
Intents
. 그만큼Service
방송합니다Intent
~을 통해sendBroadcast()
데이터 변경에. 그만큼Activity
등록 aBroadcastReceiver
사용registerReceiver()
, 그리고 그BroadcastReceiver
들어오는 방송에 대한 통지가 있습니다. 이것은 트리거합니다Activity
최신 데이터를로드합니다Service
, 또는 방송에서 Extras에서 최신 데이터를 얻기 위해Intent
. 당신은 그 기술을 사용하는 예를 볼 수 있습니다.Service
여기.
다른 팁
이것은 관찰자 패턴의 좋은 후보처럼 들립니다. 기본적으로 귀하의 활동 (관찰자)은 백그라운드 서비스 (관찰 가능한)에 자체적으로 등록되며 활동에서 데이터를 밀거나 가져올 수 있습니다. 이 경우 관찰자는 귀하의 활동이며 관찰 가능한 것은 귀하의 서비스가 될 것입니다.
디자인 패턴에 대해 아무것도 모른다면 "헤드 퍼스트 디자인 패턴"을 구매하면 읽기 쉽고 훌륭한 정보로 가득합니다.
추신 : 지금 읽고 있습니다.
나는 왜 아무도 아무도 어떤 라이브러리에서 이벤트 버스를 사용하여 간단한 접근법을 언급하지 않았는지 정말로 궁금합니다. 물론 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에 알릴 수 있는 기능이 필요합니다.
당신은 어떤 종류의 사용할 수 있습니다 어레이어댑터 데이터를 ListView로 가져옵니다.ArrayAdapter에는 다음과 같은 메소드가 있습니다. adpater.notifyDataSetChanged() 이 메서드를 호출할 때마다 어댑터는 해당 데이터가 변경되었음을 확인하고 다음 번에 업데이트해야 한다고 목록 보기에 알립니다.