Ошибка AsyncTask и Looper.prepare()

У меня есть следующий код

class OverlayTask extends AsyncTask<Void, Void, Void> {
    @Override
    public void onPreExecute() {

        if (sites != null) {
            myMapView.getOverlays().remove(sites);
            myMapView.invalidate();
            sites = null;
        }
    }

    @Override
    public Void doInBackground(Void... unused) {
            grabShipsWithLocation();
            return (null);
    }

    @Override
    public void onPostExecute(Void unused) {
        myMapView.getOverlays().add(sites);
        myMapView.invalidate();
        isLoading = false;
    }
}

Кажется, это нормально работает на нескольких тестовых устройствах, но я вижу много ошибок, появляющихся на консоли разработчика. Я не могу понять, почему и куда поместить этот Looper.prepare(). Это необходимо?

java.lang.ExceptionInInitializerError
at com.test.appname.FinderMain$1.gotLocation(FinderMain.java:286)
at com.test.appname.MyLocation$GetLastLocation.run(MyLocation.java:89)
at java.util.Timer$TimerImpl.run(Timer.java:289)
Caused by: java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:121)
at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
at android.os.AsyncTask$InternalHandler.<init>(AsyncTask.java:421)
at android.os.AsyncTask.<clinit>(AsyncTask.java:152)

По запросу MyLocation.java

    class GetLastLocation extends TimerTask {
    @Override
    public void run() {
         lm.removeUpdates(locationListenerGps);
         lm.removeUpdates(locationListenerNetwork);

         Location net_loc=null, gps_loc=null;
         if(gps_enabled)
             gps_loc=lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
         if(network_enabled)
             net_loc=lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);

         //if there are both values use the latest one
         if(gps_loc!=null && net_loc!=null){
             if(gps_loc.getTime()>net_loc.getTime())
                 locationResult.gotLocation(gps_loc);
             else
                 locationResult.gotLocation(net_loc);
             return;
         }

         if(gps_loc!=null){
             locationResult.gotLocation(gps_loc); //Line 89
             return;
         }
         if(net_loc!=null){
             locationResult.gotLocation(net_loc);
             return;
         }
         locationResult.gotLocation(null);
    }
}

person Lee Armstrong    schedule 15.11.2010    source источник
comment
Что делает GrabShipsWithLocation()?   -  person Falmarri    schedule 15.11.2010
comment
Какая строка MyLocation.java:89? добавить комментарий к источнику.   -  person blindstuff    schedule 15.11.2010
comment
Вы создаете/запускаете AsyncTask из основного потока?   -  person gngr44    schedule 15.11.2010
comment
Пожалуйста, добавьте метод gotLocation() или хотя бы фрагмент, который инициализирует класс OverlayTask.   -  person Draško Kokić    schedule 30.05.2012


Ответы (2)


Долгая история:

AsyncTask внутри использует Handler. Обработчик в основном позволяет вам отправлять Runnables из другого потока в поток, которому был назначен обработчик, который в случае AsyncTask всегда является потоком, из которого он вызывается. Однако это работает только для потоков, для которых подготовлено Looper.

Для получения дополнительной информации см. http://developer.android.com/reference/android/os/Handler.html< /а>

Короткий рассказ:

Просто оберните каждый вызов FinderMain$1.gotLocation или создание AsyncTask внутри него в Runnable и отправьте его в Handler, привязанный к потоку пользовательского интерфейса, например так:

class GetLastLocation extends TimerTask {
    private Handler mHandler = new Handler(Looper.getMainLooper());

    @Override
    public void run() {
       // ...
       mHandler.post(new Runnable() {
          public void run() {
              locationResult.gotLocation(null);
          }
       });
       // ...
     }
}
person Timo Ohr    schedule 18.11.2010
comment
Просто locationResult.gotLocation(null); в новом разделе или во всем выше? - person Lee Armstrong; 19.11.2010
comment
Или каждый locationResult.gotLocation(stuff) ?? - person Lee Armstrong; 19.11.2010
comment
Все вызовы gotLocation должны выполняться в потоке пользовательского интерфейса, то есть в Runnable, как указано выше. Вы также можете обернуть в него весь раздел, но имейте в виду, что это может замедлить ваш пользовательский интерфейс, если его выполнение займет слишком много времени. В качестве альтернативы вы также можете обернуть создание AsyncTask внутри gotLocation в Runnable, как это. - person Timo Ohr; 19.11.2010
comment
Кажется, это работает, и я опубликовал обновление, однако при попытке обернуть locationResult.gotLocation(net_loc); он хочет, чтобы я объявил net_loc окончательным, что затем прерывает вызовы над ним - person Lee Armstrong; 23.11.2010
comment
Определите net_loc как элемент GetLastLocation или сделайте его окончательным и присвойте ему значение null только в блоке else начального предложения if, а не в объявлении. - person Timo Ohr; 24.11.2010
comment
Хорошее объяснение. Действительно, я ожидал этого ответа. - person BABU K; 24.12.2014
comment
Потрясающий ман, спас мой день .. :) - person Sachin Varma; 27.02.2018

Я пробовал это ... Это сработало, надеюсь, это поможет вам ..

protected class Asyctast extends AsyncTask<String, Integer, Integer>
{

    @Override
    protected Integer doInBackground(String... params) {
        // TODO Auto-generated method stub


        Log.d("Asynctask", ""+params);  
Looper.prepare();   

         ImageThumbnailsActivity m = new ImageThumbnailsActivity();

            Toast.makeText(ImageThumbnailsActivity.this,""+params ,Toast.LENGTH_SHORT).show();
            final Dialog dialog_options = new Dialog(ImageThumbnailsActivity.this);
            dialog_options.setContentView(R.layout.option);
            dialog_options.show();
        Looper.loop();
        return null;
    }       
}
person Nilesh Tupe    schedule 13.03.2011
comment
Это нехорошее решение, потому что Looper.loop() будет заблокирован навсегда, а Thread никогда не будет выполнен. Вы должны использовать Looper.myLooper().quit(), чтобы избежать этого. Кроме того, если вам нужно вызвать Looper.prepare() из Thread - используйте Thread вместо AsyncTask. - person Borg8; 28.11.2012