我正在寻找一些类似于 Activity.onPause() 的回调,但更通用(我没有 Activity,因为这段代码在后台运行)在我的应用程序被终止之前调用。我没有尝试 Application.onLowMemory() 因为根据文档,它并不总是被调用 [我的意思是当我通过后退或主页按钮退出某些 Activity 时,我的应用程序也可能(而且我知道有时是)被杀死]。
我的应用程序中有一个 LocationListener 类,它执行一些相当繁重的计算,因此我使用了一些“缓存”或优化。我只会在位置发生很大变化或经过足够长的时间后才进行繁重的计算。
我注意到大多数时候,即使我没有移动手机,我的繁重计算代码也会被一次又一次地调用。原来是因为 oldLocation 为 null(我的 app 被 android killed) app 可以工作,因为它被 LocationService 唤醒,但是它“忘记”了缓存的 lastLocation(=null)。所以我添加了 saveLastLocation() 这确实有帮助,但我试图找出调用它的最佳位置。一开始我从 finalize() 调用它,但它从未被调用过。 android 似乎“太快”杀死了我的应用程序,以至于无法调用它。然后我将它移动到它的当前位置,就在繁重的计算之后。
我想知道是否有一种方法,类似于我在一个 Activity 中使用 onPause() 调用 saveLastLocation 并使用 onResume 调用 loadLastLocation 的理想方法。
我将 MyLocationListener 的实例保存为 MyApplication 的静态成员(用于缓存目的)
class MyLocationListener implements LocationListener {
private static MyLocationListener instance;
private Location lastLocation;
public static MyLocationListener getInstance() {
if (null == instance) {
instance = new MyLocationListener();
}
return instance;
}
private MyLocationListener() {
loadLastLocation();
}
@Override
public synchronized void onLocationChanged(final Location location) {
if (null == lastLocation || lastLocation.distanceTo(location) > MIN_LOCATION_CHANGE_DISTANCE
|| getElapsedNanoSec(location) - getElapsedNanoSec(lastLocation) > MIN_LOCATION_CHANGE_NANOSEC) {
// Just to see how many times we enter the heavy calculations
Toast.makeText(MyApp.getContext(), "old: " + lastLocation + "new: " + location, Toast.LENGTH_LONG).show();
// do the heavy calculations
lastLocation = location;
// Is there a better way to call saveLastLocation???
saveLastLocation();
}
}
private synchronized void saveLastLocation() {
final SharedPreferences sharedPreferences = getSharedPreferences();
SharedPreferences.Editor editor = sharedPreferences.edit();
if (null != lastLocation) {
editor.putString(PREF_LAST_LOCATION_PROVIDER, lastLocation.getProvider());
editor.putLong(PREF_LAST_LOCATION_ELAPSED_REALTIME, getElapsedNanoSec(lastLocation));
putDouble(editor, PREF_LAST_LOCATION_LATITUDE, lastLocation.getLatitude());
putDouble(editor, PREF_LAST_LOCATION_LONGITUDE, lastLocation.getLongitude());
editor.apply();
}
}
private synchronized void loadLastLocation() {
final SharedPreferences sharedPreferences = getSharedPreferences();
final String provider = sharedPreferences.getString(PREF_LAST_LOCATION_PROVIDER, null);
if (null != provider) {
final long elapsed = sharedPreferences.getLong(PREF_LAST_LOCATION_ELAPSED_REALTIME, Long.MIN_VALUE);
final double latitude = getDouble(sharedPreferences, PREF_LAST_LOCATION_LATITUDE, Double.MIN_VALUE);
final double longitude = getDouble(sharedPreferences, PREF_LAST_LOCATION_LONGITUDE, Double.MIN_VALUE);
if (null == lastLocation) {
lastLocation = new Location(provider);
} else {
lastLocation.setProvider(provider);
}
setElapsedNanoSec(lastLocation, elapsed);
lastLocation.setLatitude(latitude);
lastLocation.setLongitude(longitude);
}
}
private long getElapsedNanoSec(final Location location) {
long elapsed;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
elapsed = location.getElapsedRealtimeNanos();
} else {
elapsed = location.getTime() * 1000;
}
return elapsed;
}
}
澄清一下:Google Play 服务不会直接调用 MyLocationListener,我有另一个正在调用的“真实”LocationListener,从它的 onLocationChanged 我调用 MyLocationListener.getInstance().onLocationChanged(location) [我这样做的原因这是我在我的代码中的许多地方使用大量计算的结果(通过调用此处未介绍的其他函数),我希望它尽可能多地缓存]
最佳答案
如果您使用新的 FusedLocationProviderApi (它取代了 Google Play Services 6.5 中的 LocationClient
),然后你可以设置一个 smallest displacement作为您的 LocationRequest
的一部分,这将确保您只会在位置变化超过您的最小位移时收到回调 - 这确保您每次收到回调时都能够进行繁重的计算.
如果你真的还需要在一定时间后重新计算,你可以用AlarmManager设置一个闹钟。在收到的每个位置更新上充当超时机制(并取消先前设置的警报),如果没有位置更新,这将触发您的繁重计算方法,使用 FusedLocationApi.getLastLocation()作为当前位置(如果您愿意,也可以使用缓存值)。
请注意,FusedLocationProviderApi
还提供了一个 requestLocationupdates()采用 PendingIntent
的方法 - 这非常适合不想或不需要维护持续运行的监听器但想要触发短时间运行的处理程序的后台服务(IntentService 非常适合) 响应一个事件。这确保您的应用程序将始终收到更新,即使应用程序被 Android 停止也是如此。
关于android - 我可以在类似于 Activity.onPause() 的应用程序中使用什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27806782/