优先考虑IntentService中的意图

时间:2015-02-27 11:09:21

标签: android service intentservice android-intentservice android-webservice

以下是我现在所做的事情:

  1. 我有一个在后台运行并读取用户位置的服务。每次读取有效位置(有一些参数,如距离和时间),IntentService就会启动将该位置发送到Web服务器

  2. 使用跟踪服务的应用也会进行一些网络通话,具体取决于用户按哪些选项。现在,该应用程序只是在asynctask中调用Web服务。

  3. 一些代码: 每次收到好位置时,位置服务都会触发IntentService,如下所示:

    Intent intentService = new Intent(LocationLoggerService.this, LocationManagerIntentService.class);
    intentService.putExtra(Constants.MESSAGE_LOCATION, readLocation);
    startService(intentService);
    

    intentservice处理意图:

    @Override
    protected void onHandleIntent(Intent intent) {
         LocationInfo location = intent.getExtras().getParcelable(Constants.MESSAGE_LOCATION);
       .... //Do the web call and broadcast result to app
    }
    

    以下是我需要做出的更改:

    1. IntentService和应用程序不能同时调用Web服务器。由于现在实施,这是不可能的,因为它们独立行动。我想通过为所有这些调用创建意图,将所有Web调用从应用程序传递到IntentService。这会有用吗?如果有一个位置网络发送,应用程序调用的新意图将被放入队列并在当前通话后立即执行?

    2. 如果由于网络速度较低而在队列中发送多个位置,则需要将应用程序调用放在队列前面,而不是等待所有现有意图完成,仅针对当前目标。有没有办法将意图置于队列之上?

    3. 谢谢。

      稍后编辑:

      以下是我所做的更改。

      1. 创建了自定义意图服务
      2. public abstract class PriorityIntentService extends Service {
              private final AtomicInteger     intentsCount    = new AtomicInteger();
        
          protected void intentFinished() {
              intentsCount.decrementAndGet();
          }
        
          private final class ServiceHandler extends Handler {
              public ServiceHandler(Looper looper) {
                  super(looper);
              }
        
              public final boolean sendPriorityMessage(Message msg) {
        
                  intentsCount.incrementAndGet();
        
                  int priority = msg.arg2;
        
                  if (priority == 0) {
                      return sendMessageAtFrontOfQueue(msg);
                  } else {
                      return sendMessage(msg);
                  }
        
              }
        
              @Override
              public void handleMessage(Message msg) {
                  onHandleIntent((Intent) msg.obj);
        
                  if (intentsCount.get() == 0) {
                      // stopSelf(msg.arg1);
                      stopSelf();
                  }
              }
          }
        
        
          @Override
          public void onStart(Intent intent, int startId) {
        
              Message msg = mServiceHandler.obtainMessage();
              msg.arg1 = startId;
              msg.obj = intent;
        
              if (intent.getExtras().getInt(Constants.MESSAGE_PRIORITY) == 0) {
                  msg.arg2 = 0;
              } else {
                  msg.arg2 = 1;
              }
        
              mServiceHandler.sendPriorityMessage(msg);
              // mServiceHandler.sendMessage(msg);
          }
        }
        
        1. 另一项服务:
        2. public class LocationManagerIntentService extends PriorityIntentService {
          
              @Override
                protected void onHandleIntent(Intent intent) {
          
                intentFinished();
                }
          }
          

1 个答案:

答案 0 :(得分:1)

由于构建IntentService的方式无法实现您的目标,但IntentService是一个非常简单的代码并且是开源的,因此您可以只需稍加修改即可创建自己的版本。

原始代码为here

onCreate()方法中,您可以看到Service创建HandlerThread的位置以及Handler调度所有onHandleIntent来电。

所以你要做的就是:

  • 为您的整个应用程序创建单身HandlerThreadHandler。每次网络电话或CustomIntentService都应调用此单Handler。那是第1部分。你只是强迫所有的网络呼叫永远不会同时发生。

  • 现在您通过相同的线程和处理程序进行了所有调用,只需要调用Handler.postAtFrontOfQueue来确定某些执行的优先级。

快乐的编码。

修改

新修改:

它没有执行的原因在于:

stopSelf(msg.arg1);

一旦所有正在执行的消息都停止服务,请检查the docs

  

如果服务的最近开始时间是startId,请停止服务。   这与为此特定调用stopService(Intent)相同   服务,但如果有一个开始,你可以安全地避免停止   来自客户的请求,您尚未在onStart(Intent, int)中看到。

     

请注意对此功能的调用顺序。如果你打电话   此函数具有最近收到的ID,然后才能使用   将其称为先前收到的ID,该服务将立即生效   无论如何都停了。如果您最终可能无序处理ID(例如   通过在不同的线程上调度它们,然后你负责   按照收到它们的顺序停止它们。

因此,在完成之前,您必须找到另一种检查所有消息是否已执行的方法。可能是AtomicInt计算队列中的邮件数量,或者是用来保存startId的地图。