在FusedLocationProviderClient.requestLocationUpdates()中使用Looper.myLopper()或null是否是同一件事?

时间:2019-06-24 00:53:25

标签: android android-looper fusedlocationproviderclient

我正在使用FusedLocationProviderClient.requestLocationUpdates()方法创建一个位置跟踪应用。其参数之一需要一个Looper对象,但我不确定它是如何工作的。现在,我刚刚将null传递给它,它可以按预期工作。

经过研究,我了解到UI线程基本上是一个HandlerThread,它已经具有自己的Looper对象(我了解基本知识,但是意识到有点晚了)。因此,这次我使用Looper.myLooper()而不是null,它仍然有效。

private void getLocationUpdates(){
//checkSelfPermissions
fusedLocationProviderClient
.requestLocationUpdates(locationRequest,locationCallback,Looper.myLooper());
}

文档说,传递null会在调用线程上执行locationCallback。因此,当我使用Looper.myLooper()时会发生什么。从字面上的任何线程调用时,两者的作用相同吗?还是我缺少了什么?

2 个答案:

答案 0 :(得分:1)

如果您在主线程中调用 getLocationUpdates 方法,那么 locationCallback 也将在主线程中执行。 如果您在后台线程中调用 getLocationUpdates ,并且将null传递给循环程序,则您的回调将在后台线程中执行。 这取决于您的需要,您是否确实需要指定在哪个线程中执行回调。

答案 1 :(得分:1)

document中添加更多信息: Callbacks for LocationCallback will be made on the specified thread, which must already be a prepared looper thread.

在您理解传递nulllooper作为值3rd参数之间的区别之前,您需要了解以下内容:looper / handler / {{1 }}(因为您提到了HandlerThread,所以我将其与其他两个一起放在这里)。

关于这些概念的文章很多,这里仅是仅供参考:


所以我希望我可以尝试尽可能简单地回答。

当您说: HandlerThread

我假设您当时没有启动任何新线程(例如,没有I'm creating a location tracking app for which I'm using the FusedLocationProviderClient.requestLocationUpdates() method. One of its argument requires a Looper object and I'm not completely sure how it works. Right now I'm just passing null to it and it works as expected.或没有new Thread()),如果是这样,很有可能您正在调用方法{{1} }在Android主线程(即默认线程)中,您可以在该线程上更新视图(例如,默认情况下,您可以毫无问题地运行new HandlerThread(),这是因为您在主线程中-aka UI线程,默认情况下),因此传递getLocationUpdates()将在textView.setText("xx")上执行回调,即:主线程。现在您需要知道,主线程有一个循环程序,我们可以称其为主循环程序。

然后您说: null

我认为您做了如下操作:

calling thread

这次您通过了After researching I learned that the UI Thread is basically a HandlerThread which already has its own Looper object (I know basic stuff but realized a bit late). So I used Looper.myLooper() instead of null this time and it still works.作为第三个参数。

通过这种方式,您提供了一个HandlerThread handlerThread = new HandlerThread(); getLocationUpdates(); private void getLocationUpdates(){ //checkSelfPermissions fusedLocationProviderClient .requestLocationUpdates(locationRequest,locationCallback,Looper.myLooper()); } ,并且Looper.myLooper()将在该looper的特定线程上执行(稍后再讨论弯针)。

但是,因为很有可能您再次在主线程中调用locationCallback,所以looper仍返回主线程中的循环程序,是的,您可以考虑使用getLocationUpdates()仍在主循环程序上运行,与您在上方设置的Looper.myLooper相同。

但是,如果您对代码进行如下更改:

callback

null将在指定的循环程序线程上执行,即:从HandlerThread handlerThread = new HandlerThread(); handlerThread.start(); getLocationUpdates(handlerThread.getLooper()); private void getLocationUpdates(Looper looper){ //checkSelfPermissions fusedLocationProviderClient .requestLocationUpdates(locationRequest, locationCallback, looper); } 获得的循环程序对象。

那地球上有什么区别?

创建新的callback并启动它时,您正在启动新的handler.getLooper(),并且HandlerThread将默认在处理程序所在的位置调用Thread线程会创建一个新的handlerThread.start(),并准备好此弯针,并与您刚才创建的HandlerThread#run()绑在一起。

如果您尝试在回调中更新UI元素(例如,更新textview或mapview),则会看到真正的区别。因为仅在UI线程上允许UI更新,所以如果设置looper,则在尝试更新UI时会遇到异常;并且如果您在主线程中设置handlerThreadhandlerThread.getLooper() 也没有问题,那么强调null的原因是,Looper.myLooper()将在不同线程上运行时引用不同的looper对象。

谈谈Looper:使用main thread对象,您可以新建一个处理程序,然后将Looper传递给它,例如:Looper.myLooper,然后在调用looper时,可运行对象将可以在您在处理程序上设置的循环程序线程上执行,我认为这就是API在后台执行的操作。

我认为,阅读更多有关Handler handler = new Handler(looper) / handler.post(new Runnable(...)) / handler的文章会有所帮助。