3 つのアクティビティと 2 つのサービスを備えた Android アプリを開発したいと考えています。
WebClientServiceという名前の最初のサービスは、ハンドラーを使用して 30 秒ごとに REST API を呼び出し、アクティブなアクティビティに結果を通知する必要があります。また、ローカル DB を更新するために、DatabaseServiceという名前の 2 番目のサービスに通知する必要があります。
データベース サービスは、アクティビティのonCreateで 1 回だけ呼び出され (アプリのクラッシュと再起動の場合)、onRestartで 1 回だけ呼び出されます(このようにして、接続の問題が発生した場合にデータを表示できます)。アクティビティは、30 秒ごとに「生きている」アクティビティを通知する WebClientService のおかげで、自分自身を更新し続けます。
質問は次のとおりです。
アクティブなアクティビティとバックグラウンドの DatabaseService の両方の更新を通知する最善の方法は何ですか? 私の考えは、WebClientService 内でsendBroadcast()を使用し、すべてのアクティビティと DatabaseService 内でBroadcastReceiverを使用することです。これは正しいアプローチですか?
AllMeetingRoomActivity と DatabaseService の間の通信に同じアプローチを使用する必要がありますか、それともBound Serviceを使用する必要がありますか?
ありがとう
UPDATE : DatabaseService はもはやバックグラウンド サービスではなく、WebClientService とアクティビティの間の db レイヤーの単なる共有インスタンスです。
質問は次のとおりです。ローカル データベースに 30 秒の更新を書き込むだけで、アクティビティがローカル データベースから読み取るだけで数秒ごとに自分自身を更新できるようにするのは良い方法ですか? それはパフォーマンスに大きく影響しますか?
環境:
これまでに実装したものに従いますが、SettableFutures を使用しているため、サービスとブロードキャストを効果的に通信させる方法を明確にしたら、サービスとブロードキャストを使用して再実装する必要があります。
public class MainActivity extends AppCompatActivity {
private TextView meetingsTextView;
private EditText mEdit, editSubject;
private final ConnectorInitializer clientInitializer = new ConnectorInitializer();
private AppConnector genericClient; // can use OutlookClient or a test client to talk with a mock server
@Override
protected void onCreate(Bundle savedInstanceState) {
// initializes client based on the settings in "config.json"
genericClient = clientInitializer.create(this);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
meetingsTextView = (TextView) findViewById(R.id.NowMeeting);
mEdit = (EditText)findViewById(R.id.editText);
editSubject = (EditText)findViewById(R.id.editSubject);
Futures.addCallback(genericClient.logon(this, scopes), new FutureCallback<Boolean>() {
@Override
public void onSuccess(Boolean result) {
Log.d("APP", "-- Logged in. --");
databaseConnector.synchronouslyGetBackupFromLocalDatabase() // FUTURE
// callback here
// onSuccess, onFailure
}
@Override
public void onFailure(@NonNull Throwable t) {
Log.e("\n ~~~~>> logon \n", t.getMessage());
meetingsTextView.setText(R.string.Login_Failed);
}
});
}
/** At the moment the UI is not updated automatically every 30 seconds
* but manually using a refresh button
*/
public void getBookings(@SuppressWarnings("UnusedParameters") View view){
Log.d("APP", "Retrieve button clicked: "+(DateTime.now())+". Calling async getCalendar.");
meetingsTextView.setText(R.string.retrieving_events);
try{
Futures.addCallback( genericClient.getCalendarEvents(), new FutureCallback<String>(){
@Override
public void onSuccess(final String resultCalendars) {
Log.d("APP", "Success. Result: "+resultCalendars);
runOnUiThread(new Runnable() {
@Override
public void run() {
Log.d("APP", "Calendars SUCCESSFULLY retrieved.");
String meetingsRetrieved = getString(R.string.calendar)+resultCalendars;
meetingsTextView.setText(meetingsRetrieved);
Toast.makeText(getApplicationContext(), "Success!", Toast.LENGTH_LONG).show();
}
});
databaseConnector.asyncUpdateLocalDbWithResults(); // FUTURE
// callback here
// onSuccess, onFailure
}
@Override
public void onFailure(@NonNull Throwable t) {
Log.e( "APP", "Calendar error. Cause: "+t.getLocalizedMessage() );
String retrieveError = "Retrieve error. \n\n\n"+t.getLocalizedMessage();
meetingsTextView.setText(retrieveError);
Toast.makeText(getApplicationContext(), "Fail!", Toast.LENGTH_LONG).show();
}
});
}catch(Exception ex){
Log.e("APP","Something went wrong in your code. Cause:"+ex);
}
}