2013-10-24 3 views
2

У меня есть IntentService со своим собственным процессом, правильно так:ANR в IntentService со своим собственным процессом

AndroidManifest.xml

<service 
    android:name="com.app.services.UpdateDatabaseService" 
    android:process=":updateDatabaseService" 
    android:label="@string/service_name" 
    android:exported="false" > 
</service> 

Затем, когда IntentService работает, он создать две темы , Одна из задач, по которой поток является длинной задачей (более 1 минуты). И я получаю вопрос ANR.

10-24 18:51:27.923: E/ActivityManager(148): ANR in com.app:FooService 
10-24 18:51:27.923: E/ActivityManager(148): Reason: Executing service com.app/.services.FooService 
10-24 18:51:27.923: E/ActivityManager(148): Load: 1.08/0.48/0.21 
10-24 18:51:27.923: E/ActivityManager(148): CPU usage from 13433ms to 1122ms ago: 
10-24 18:51:27.923: E/ActivityManager(148): 92% 1375/com.emanga:updateMangaDatabase: 87% user + 5.7% kernel/faults: 5740 minor 
10-24 18:51:27.923: E/ActivityManager(148): 0.4% 148/system_server: 0.2% user + 0.1% kernel/faults: 13 minor 
10-24 18:51:27.923: E/ActivityManager(148): 0.2% 45/adbd: 0% user + 0.2% kernel 
10-24 18:51:27.923: E/ActivityManager(148): 0.1% 758/logcat: 0% user + 0.1% kernel 
10-24 18:51:27.923: E/ActivityManager(148): 0% 266/com.android.phone: 0% user + 0% kernel/faults: 2 minor 
10-24 18:51:27.923: E/ActivityManager(148): 93% TOTAL: 87% user + 6.2% kernel + 0% irq 
10-24 18:51:27.923: E/ActivityManager(148): CPU usage from 1804ms to 2442ms later: 
10-24 18:51:27.923: E/ActivityManager(148): 70% 1375/com.emanga:updateMangaDatabase: 65% user + 4.9% kernel/faults: 123 minor 

Ни в коем случае пользовательский интерфейс не блокируется. Итак, если служба находится в отдельном процессе (а не в потоке пользовательского интерфейса), почему я получаю эту ошибку?

EDIT 1:

Я изменил IntentService в услужении, но я получаю тот же вопрос еще. Я попробую объяснить, что я хочу получить. В архитектуре моего приложения есть действия, которые показывают данные, восстановленные из базы данных с помощью Loaders. Если в базе данных нет запрошенных данных, она будет запрашивать службу, которая будет восстанавливать данные из Интернета (служба управляет интернет-запросами, анализирует некоторые html, обновляет базу данных новыми данными, а в конце служба уведомляет об изменениях)

Эта услуга имеет свой собственный процесс, потому что, хотя улов услуг исключения, которые могли бы произойти, таким образом, приложение является Robuster от интернета или анализатора сбоев (приложение не будет врезаться)

цель грузчиков игрового заключается в получении данных из базы данных, и целью службы является получение данных из Интернета и обновление базы данных. Связь между Loaders и Services предназначена только для уведомления об изменениях или запросах.

Наконец, у этой службы есть очередь задач и исполнитель, выполняющий задачи.

public class UpdateDatabaseService extends Service { 

    private static final String ACTION = "com.app.services.UpdateDatabaseService"; 
    public static final String ACTION_TASK_1 = ACTION + ".latestChapters"; 
    public static final String ACTION_TASK_2 = ACTION + ".latestMangas"; 

    private static final byte PARALLELTASKS = 2; 

    public LinkedBlockingQueue<Runnable> tasks = new LinkedBlockingQueue<Runnable>(); 

    private ExecutorService executor = Executors.newFixedThreadPool(PARALLELTASKS); 

    private final IBinder mBinder = new MyBinder(); 

    public class MyBinder extends Binder { 
     public UpdateDatabaseService getService() { 
      return UpdateDatabaseService.this; 
     } 
    } 

    @Override 
    public IBinder onBind(Intent arg0) { 
     return mBinder; 
    } 

    @Override 
    public void onCreate(){ 
     // By default always it does DefaultTask1 
     tasks.put(new DefaultTask1()); 

     if(!isEmptyTable("tableFoo")){ 
      tasks.put(new DefaultTask2()); 
     } 

     executor(); 
    } 

    public int onStartCommand(Intent intent, int flags, int startId) { 

     if(intent != null && intent.getAction() != null) { 

      String action = intent.getAction(); 
      if(action == ACTION_TASK_1){ 
         tasks.put(new Task1()); 
      } else 
      if(action == ACTION_TASK_2){ 
       tasks.put(new Task2()); 
      } 
     } 


     // We want this service to continue running until it is explicitly 
      // stopped, so return sticky. 
     return START_STICKY; 
    } 

    private void executor(){ 

     while(true){  
       executor.execute(tasks.take()); 

    } 


} 
+1

Укажите, какой код вы можете использовать в своем сервисе, здесь нет ничего полезного. – schwiz

ответ

4

Каждый процесс имеет резьбу основного приложения (UI). Это поток, который вызывает методы жизненного цикла вашего компонента, такие как onStartCommand() из Service. И вы не можете связать эту нить, или вы получите ANR.

Как правило, это не проблема с IntentService. Нет IntentService Подкласс должен создавать собственные потоки, поэтому важны только два важных потока: основной поток приложений и IntentService - используемый фоновый поток (тот, который вызывает onHandleIntent()). Убедитесь, что все ваши работы находятся в onHandleIntent(). Если вы разворачиваете дополнительные потоки самостоятельно, либо избавляетесь от них, либо переключаетесь с IntentService на обычный Service, так что вы можете организовать для Service выход, только когда все ваши темы выполняются с их работой, а не когда onHandleIntent() сделан.

Кроме того, я настоятельно рекомендую вам избавиться от android:process, так как вы тратите впустую процессор и оперативную память без каких-либо очевидных дополнительных преимуществ для пользователя.

+0

Полезное объяснение. Я добавляю код и информацию об этой проблеме (Edit 1), потому что мне нужен этот процесс для заполнения базы данных приложения, а затем служба будет управлять базой данных обновлений с помощью интернет-ресурсов. Я думаю, что это преимущество для пользователя, и только критический первый случай. –

+0

@Franb: «У этой службы есть свой собственный процесс, потому что, хотя служба улавливает исключения, которые могут произойти, таким образом приложение является роботом в отношении сбоев интернета или парсера (приложение не будет аварийно завершено)» - это не действительная причина иметь несколько процессов в среде с ограниченными ресурсами, например мобильное устройство. Опять же, вы тратите впустую RAM, CPU и батарею. – CommonsWare

+0

Итак, когда вы используете отдельный процесс вместо потока? или Каковы случаи, когда хорошая практика использует процесс? –

Смежные вопросы