【问题标题】:android service notify activity completed best way?android服务通知活动完成的最佳方式?
【发布时间】:2011-09-29 08:21:56
【问题描述】:

我创建了一个服务,该服务在后台线程上同步来自网络的数据,并希望在服务完成时通知列表活动,以便它可以更新它的光标?最好的方法是什么?我正在考虑在服务完成后发送广播,但不确定这是否是最好的方法。服务完成后我需要重新查询光标,所以我不确定这是否适用于广播接收器?好久没做android了,先谢谢了。

【问题讨论】:

    标签: android android-service android-cursor


    【解决方案1】:

    当您的ListActivity 连接到服务时,在您的服务中使用Handler 注册客户端;也就是说,在您的ListActivity 中的onServiceConnected 方法中,将Message 发送到您的服务,使您能够跟踪连接的客户端。然后,您可以简单地在您的Service 中遍历这些客户端,并在您的Service 中发生您想要通知您的ListActivity 的事情时向他们发送Message。有关更多信息,您可以查看我正在进行的项目中的代码:我的ListActivity 和我的Service stub

    简而言之,在您的MainActivity 中,使用以下命令启动并绑定到您的服务:

    Intent i = new Intent(this, NetworkService.class);
    startService(i);
    bindService(i, networkServiceConnection, Context.BIND_AUTO_CREATE);
    

    定义一个信使来响应来自服务的消息,例如:

    Messenger messenger = new Messenger(new IncomingHandler());
    
    class IncomingHandler extends Handler {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case NetworkService.MSG_SOMETHING:
                    // do something here
                    break;
                default:
                    super.handleMessage(msg);
            }
        }
    }
    

    然后编写你的服务连接代码,如:

    private ServiceConnection networkServiceConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder service) {
            networkService = new Messenger(service);
            try {
                Message msg = Message.obtain(null, NetworkService.MSG_REGISTER_CLIENT);
                msg.replyTo = messenger;
                networkService.send(msg);
                log.debug("Connected to service");
    
            } catch (RemoteException e) {
                // Here, the service has crashed even before we were able to connect
            }
        }
    

    请注意,replyTo 是我们刚刚创建的信使。

    在您的 NetworkService 中,通过以下方式跟踪连接的客户端:

    ArrayList<Messenger> clients = new ArrayList<Messenger>();
    

    并创建您的处理程序,例如:

    class IncomingHandler extends Handler {
           @Override
           public void handleMessage(Message msg) {
               switch (msg.what) {
                   case MSG_REGISTER_CLIENT:
                       log.debug("Adding client: " + msg.replyTo);
                       clients.add(msg.replyTo);
                       break;
                   default:
                       super.handleMessage(msg);
                       break;
               }
           }
       }
    

    然后,当您想将消息发送回您的MainActivity 时,只需执行以下操作:

    for (int i = 0; i < clients.size(); i++) {
        try {
            clients.get(i).send(Message.obtain(null, MSG_SOMETHING));
        } catch (RemoteException e) {
            // If we get here, the client is dead, and we should remove it from the list
            log.debug("Removing client: " + clients.get(i));
            clients.remove(i);
        }
    }
    

    【讨论】:

    • 这听起来很有希望,但仍然有点困惑,但我认为当我尝试实施时会更有意义。在执行时间和诸如广播接收器之类的东西方面是否有任何限制?我会让你知道当我编写这个代码时会发生什么。谢谢!
    • 不确定BroadcastReceivers,因为它不使用这些,而是​​在应用程序内部使用Messengers 和Handlers。但根据我的经验,我没有看到根据Service 中的事件更新我的 UI 有任何延迟。希望这对你有用!
    【解决方案2】:

    如果您已经在使用支持库,您可以使用LocalBroadcastManager 轻松地从服务中触发广播,返回到您将侦听正在发送的广播的活动。

    使用 LocalBroadcastManager 可确保只有您自己的应用程序才能接收广播,因此您不必担心泄露私人数据或打开潜在的安全漏洞。

    另见:how to use LocalBroadcastManager?

    编辑(09/2014):

    更好的方法是使用事件总线框架,如Otto(我最喜欢的)或GreenRobot/EventBus,以避免将组件耦合得太紧。

    【讨论】:

      【解决方案3】:

      根据The Busy Coder's Guide to Advanced Android Development

      Event Bus 是服务让其他部分的好方法 的应用程序知道某些工作已完成。它提供了一个标准 事件生产者和事件的通信通道(或“总线”) 消费者可以上钩。事件生产者只需要提交事件 到公共汽车;总线将处理将这些事件引导到相关的 消费者。这减少了生产者和生产者之间的耦合 消费者,有时甚至减少了源代码所需的数量 并接收这些事件。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-15
        • 2016-07-27
        • 1970-01-01
        • 1970-01-01
        • 2023-03-11
        • 1970-01-01
        相关资源
        最近更新 更多