Android服务与活动之间的通信 [英] Communication between Android Services and Activities

查看:96
本文介绍了Android服务与活动之间的通信的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想开发一个具有三个活动和两个服务的Android应用程序.

I want to develop an Android App with three activities and two services.

第一个名为 WebClientService 的服务使用Handler每30秒调用一次REST API,并且必须将结果通知活动的Activity. 它还必须通知另一个名为 DatabaseService 的服务,以更新本地数据库.

The first Service, named WebClientService, calls a REST API every 30 seconds, using an Handler, and has to notify the active Activity with the result. It also has to notify a second Service, named DatabaseService, in order to update a local DB.

将仅在活动的 onCreate 中调用一次数据库服务(如果应用程序崩溃并重新启动),而在 onRestart 中将调用一次(通过这种方式,我们可以获得数据以显示是否存在连接问题).然后,借助WebClientService每30秒通知一次活动"活动,这些活动将保持更新.

The Database Service will be called just once onCreate of the activity (in case of app crash and restart) and just once at onRestart (in this way we have data to show in case there were connectivity issues). The activities will then keep themselves updated thanks to the WebClientService that notifies the "alive" activity every 30 seconds.

问题是:

  • 通知活动活动和后台DatabaseService的更新的最佳方法是什么? 我的想法是在WebClientService中使用 sendBroadcast()

  • What's the best way to notify for an update both the active activity and the background DatabaseService? My idea is to use sendBroadcast() within WebClientService and a BroadcastReceiver in every activity and within the DatabaseService, is it the right approach?

我应该对AllMeetingRoomActivity和DatabaseService之间的通信使用相同的方法,还是应该使用绑定服务?

Should I use the same approach for the communication between AllMeetingRoomActivity and DatabaseService or should I use a Bound Service?

谢谢

更新: DatabaseService不再是后台服务,而只是WebClientService和活动之间db层的共享实例.

UPDATE: DatabaseService won't be a background service anymore but just a shared instance of the db layer between WebClientService and the activities.

现在的问题是:将我的30秒更新写入本地数据库,并允许活动仅从本地数据库读取每隔几秒钟更新一次,这是一个好方法吗?? 这会严重影响性能吗?

So question now is: is it a good approach to just write my 30 seconds updates to the local db and allow the activities to update themselves every few seconds simply reading from the local db? Would that affect the performance too much?

上下文:

遵循我到目前为止已实现但使用SettableFutures的内容,因此一旦我弄清楚如何使其有效通信,就需要使用服务和广播"重新实现它们:

Follows what I've implemented so far but using SettableFutures and thus needs to be re-implemented using Services and Broadcasts once I've clear how to make them communicate effectively:

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);
        }
    }

推荐答案

我认为BroadCastReceiver可以解决您的问题.但是,BroadCastReceiver应该用于全局目的(例如两个应用程序之间的通信).如果您打算仅将BroadCastReceiver用于您的应用程序,则我更喜欢使用 LocalBroadcastManager 代替.当LocalBroadcastManager仅由您的应用捕获时,使用它会更快,更安全.

I think your approach is ok with BroadCastReceiver. However, BroadCastReceiver should be used for a global purpose (like communicating between 2 applications). If you intend to use BroadCastReceiver for your app only, I prefer using LocalBroadcastManager instead. Using LocalBroadcastManager is faster and more security when it can be caught only by your app.

activityservice之间进行通信的另一种方法是使用 EventBus .这将比使用BroadCastReceiver容易得多(尤其是在它们之间传递数据).

There's another way to communicate between your activitys and your services is using EventBus. It will be much easier than using BroadCastReceiver (especially in passing data between them).

更新:关于您的更新问题:

Update: About your update question:

  1. 将30秒的更新内容写入本地数据库并允许活动每隔几秒钟就更新一次(仅从本地数据库读取内容),这是一种好方法吗? ->当然可以.您应该让自己的活动在需要时进行自我更新.更新本地数据库时,应该知道是否有任何更改.如果有任何更改,请使用LocalBroadcastmanager通知您的活动进行更新.
  2. 会对性能产生太大影响吗? ->是的,可以.数据库连接将花费一些时间来执行,并且在某些情况下会阻塞您的UI.在这种情况下,您应该为每个execute使用带有ExecutorService的线程(插入,更新...).需要考虑的另一件事是,频繁更新会非常非常快地耗尽手机电池.
  1. is it a good approach to just write my 30 seconds updates to the local db and allow the activities to update themselves every few seconds simply reading from the local db? --> Of course NO. You should let your activities update themselves when they need. When you update your local db, you should know that is there any changes or not. If there is any change, use LocalBroadcastmanager to notify your activity to update.
  2. Would that affect the performance too much? --> Yes, that do. The db connection will take time to execute and it will block your UI in some cases. in that case, you should use a thread with ExecutorService for each execute (insert, update...). One more thing to consider is updating that frequently will drain your phone battery very, very fast.

这篇关于Android服务与活动之间的通信的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆