FusedLocationProvider работает в основном потоке, даже если метод вызывается из другого выполняемого потока

#java #android #multithreading #performance #location

#java #Android #многопоточность #Производительность #Расположение

Вопрос:

   autoSearch_button.setOnClickListener(view -> {
        grant_permission();
        check_location_enableornot();
        lastButton_pressed = view.getId();
        ExampleRunnable exampleRunnable = new ExampleRunnable(20);
        Thread thread = new  Thread(exampleRunnable);
        thread.start();
        thread.join();
    });
 
  public class ExampleRunnable implements Runnable {
    private int kmRadius;
    private double lat =0 , longi =0 ;

    public ExampleRunnable(int i) {
        this.kmRadius = i;
    }

    @Override
    public void run() {
        lastLocation();
    }  
    
    private void lastLocation(){
        Log.i(TAG, "lastLocation: "   Thread.currentThread().getName());
        
       fusedLocationProviderClient =  LocationServices.getFusedLocationProviderClient(MainActivity.this);
       // for now being assume that i have declared     
      @SuppressLint("MissingPermission") Task<Location> locationTask = fusedLocationProviderClient.getLastLocation();
        locationTask.addOnSuccessListener(location -> {
            if (location != null) {
                //We have a location
                Log.d(TAG, "run: last location"    Thread.currentThread().getName()););
                this.lat = location.getLatitude();
                this.longi = location.getLongitude();
                print();
            } else  {
                Log.d(TAG, "onSuccess: Location was null... calling robust");
            }
        }).addOnFailureListener(e -> Log.e(TAG, "onFailure: "   e.getLocalizedMessage() ));
      }
    }
   
    public synchronized void print(){
      Log.d(TAG, "print: "   Thread.currentThread.getName());
    }
 }
 

Выводите то, что я хочу, в logcat

  • lastlocation: thread4
  • выполнить: поток lastlocation4
  • печать: thread4

Но какой результат я получаю — lastlocation: thread4 // run: lastLocation main // print: main

Я хочу обрабатывать местоположение и работать над ним в определенном потоке

Ответ №1:

locationTask.addOnSuccessListener

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

Очевидно (и это часто встречается в системах обработки событий, подобных этой), какой-то поток завершает выполнение некоторого события, и, как следствие этого, слушатели для этого события запускаются прямо тогда и там, в этом потоке.

У вас есть два решения:

  1. Потому что любое событие в конечном итоге запускает прослушиватель (ваш код не помогает объяснить, где это; то, что заставляет объект locationTask , на который указывает переменная, переходить в состояние «успех», тем самым вызывая вашего прослушивателя), происходит в том потоке, в котором вы хотите, чтобы это произошло, а не в main .
  2. Не запускайте поток для регистрации успешного прослушивателя; запустите поток внутри вашего успешного прослушивателя (поэтому вместо Log.d(TAG, "run: last location"... этого запустите поток).

Иногда системы обработки событий настраиваются, и вы можете указать ему запускать такие события в других потоках, но это случается редко. Если библиотека не поддерживает это (а я сомневаюсь, что это так), вам придется написать методы-оболочки или обернуть всю библиотеку, чтобы получить это.