首页 > 解决方案 > fusedLocationProvider 在主线程上运行,即使方法是从不同的可运行线程调用的

问题描述

  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 // run: lastLocation main // print: main

我想在特定线程中处理位置并对其进行处理

标签: javaandroidmultithreadingperformancelocation

解决方案


locationTask.addOnSuccessListener

这不会运行侦听器,它只是注册对象后面的代码块locationTask,并且该对象可以用它做任何事情。

显然(这在这样的事件处理程序系统中很常见),某个线程最终会执行某个事件,因此,该事件的侦听器会在该线程中立即运行。

你有两个解决方案:

  1. 导致最终触发侦听器的任何事件(您的代码无助于解释它在哪里;导致变量locationTask指向的对象进入“成功”状态,从而触发您的侦听器)发生在您的线程中希望它发生在,而不是主要的。

  2. 不要启动线程来注册成功监听器;在您的成功侦听器中启动一个线程(因此,而不是Log.d(TAG, "run: last location"...启动一个线程)。

有时,事件处理程序系统是可配置的,您可以告诉它在其他线程中触发此类事件,但这很少见。如果库不支持它(我怀疑它支持),您必须编写包装器方法或包装整个库来获得它。


推荐阅读