Можно ли использовать AsyncTask в классе службы?

Все в названии.

В официальной документации указано, что Note that services, like other application objects, run in the main thread of their hosting process и AsyncTask работают только в том случае, если они выполняются в UIThread.

Так можно ли использовать AsyncTask в классе службы?

Я пытаюсь сделать это, но я всегда получаю ту же ошибку

05-01 18:09:25.487: ERROR/JavaBinder(270): java.lang.ExceptionInInitializerError

...

05-01 18:09:25.487: ERROR/JavaBinder(270): Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

Я что-то не так делаю или это просто невозможно?

Вот код моего класса обслуживания

package com.eip.core;

import android.app.Service;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

public class NetworkService extends Service {


    private final INetwork.Stub mBinder = new INetwork.Stub() {

        @Override
        public int doConnect(String addr, int port) throws RemoteException {
            new ConnectTask().execute("test42");
            return 0;
        }
    };

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

    private class ConnectTask extends AsyncTask<String, Void, Void> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            Log.i("OnPreExecute()", "");
        }

        @Override
        protected Void doInBackground(String... arg0) {
            Log.i("doInBackground()", "");
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);
            Log.i("OnPostExecute()", "");
        }

    }
}

person Spredzy    schedule 01.05.2010    source источник


Ответы (5)


Также не забудьте проверить IntentService. Если этого класса достаточно для ваших нужд, он позаботится о множестве мелких деталей, связанных с корректной работой шаблона.

person hackbod    schedule 01.05.2010

Думаю, я нашел, почему это не работает в моем случае.

Здесь я использую это:

private final INetwork.Stub mBinder = new INetwork.Stub() {

        @Override
        public int doConnect(String addr, int port) throws RemoteException {
            new ConnectTask().execute("test42");
            return 0;
        }
    };

Я использую это для так называемого IPC, Inter Process Communication, поэтому я предполагаю, что моя служба и моя активность находятся в двух разных процессах, AsyncTask должен выполняться в основном потоке пользовательского интерфейса в соответствии с Android doc, поэтому то, что я пытался сделать, кажется мне просто невозможным в соответствии с этими фактами.

Если я ошибаюсь, пожалуйста, кто-то может меня поправить.

person Spredzy    schedule 05.05.2010

Возможно, проблема не в AsyncTask, а в чем-то другом. Например, вы уверены, что ваш метод onBind работает правильно? Пожалуйста, попробуйте это:

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

Вы также можете попробовать это

public class NetworkService extends Service{
  @Override
  public void onStart(Intent intent, int startId) {
    new ConnectTask().execute("test42");
  }
}
person Fedor    schedule 01.05.2010

Можно ли использовать AsyncTask в классе службы?

да. См. Reto Meier (2010) Professional Android 2 Application Development, Wrox. Мейер опубликовал вспомогательный код (см. /Глава 9 Землетрясение 4/src/com/paad/earthquake/EarthquakeService.java):

public class EarthquakeService extends Service {        
    ... 
    private EarthquakeLookupTask lastLookup = null;
    ...

    private class EarthquakeLookupTask extends AsyncTask<Void, Quake, Void> { 
        ... 
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {    
        ...
        refreshEarthquakes();
        return Service.START_NOT_STICKY;
    };

    private void refreshEarthquakes() {
        ...
        lastLookup = new EarthquakeLookupTask();
        lastLookup.execute((Void[])null);
        ...
    }
}

Кроме того, я не могу найти никаких доказательств в поддержку вашего утверждения о том, что «AsyncTask работает только в том случае, если он выполняется в UIThread» (хотя это было бы нарушать правила создания потоков).

person user2768    schedule 07.08.2014
comment
Привет, это не нарушает правила многопоточности, так как ваша служба всегда работает в потоке пользовательского интерфейса, пока вы не разветвите потоки из него. - person user1530779; 05.02.2015
comment
Таким образом, приведенный выше код будет работать нормально, я думаю, вы запутались между службами и службами намерений. Службы намерений по умолчанию работают в фоновом потоке. - person user1530779; 05.02.2015

Хотя можно использовать AsyncTask в классе Service, это нарушает правила многопоточности, в частности , AsyncTask должен создаваться и вызываться в потоке пользовательского интерфейса. (См. https://stackoverflow.com/a/25172977/3664487 для дальнейшего обсуждения.)

person user2768    schedule 14.08.2014