我可以在类似于 Activity.onPause() 的应用程序中使用什么

What can I use in Application that is similar to Activity.onPause()

我正在寻找一些类似于 Activity.onPause() 的回调,但更通用(我没有 Activity,因为此代码在后台运行),即在我的应用程序被杀死之前调用。我没有尝试 Application.onLowMemory() 因为根据文档,它并不总是被调用 [我的意思是当我退出某些 activity 时,我的应用程序也可能(而且我知道有时是)被杀死或主页按钮]。

我的应用程序中有一个 LocationListener class,它执行一些相当繁重的计算,因此我使用了一些 "caching" 或优化。我只在位置变化很大或经过足够时间时才进行繁重的计算。

我注意到大多数时候,即使我不移动手机,我的繁重计算代码也会被一次又一次地调用。事实证明,这是因为 oldLocation 为 null(我的应用程序被 android 杀死)该应用程序可以正常工作,因为它被 LocationService 唤醒,但它 "forgets" 缓存的 lastLocation(=null)。所以我添加了 saveLastLocation() 这确实有帮助,但我试图找出调用它的最佳位置。一开始我从 finalize() 调用它,但它从未被调用过。似乎 android 杀死了我的应用程序 "too fast" 以便它被调用。然后我把它移动到它现在的位置,在繁重的计算之后。

我想知道是否有一种方法,类似于我在 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 播放服务不直接调用 MyLocationListener,我有另一个正在调用的 "real" LocationListener,我从它的 onLocationChanged 调用 MyLocationListener.getInstance() .onLocationChanged(location) [我这样做的原因是我在我的代码中的许多地方使用了繁重的计算结果(通过调用这里没有介绍的其他函数),我希望它尽可能多地缓存]

我建议采用不同的方法。你为什么不使用警报管理器定期唤醒服务(理想情况下使用不精确的警报)来获取当前位置并检查它是否已经足够改变,然后在服务内部进行大量计算并将结果存储在数据库中或文件。

这样您就可以在更受控的环境中进行繁重的计算 运行。

您也可以使用新的 JobScheduler (5+) 而不是警报管理器。如果您需要兼容版本,可以通过一个项目将 JobScheduler 恢复到 API 10+ (https://github.com/evant/JobSchedulerCompat)

如果您使用新的 FusedLocationProviderApi (which replaces the LocationClient in Google Play Services 6.5), then you can set a smallest displacement 作为 LocationRequest 的一部分,这将确保您只会在位置变化超过最小位移时收到回调 - 这确保您会每次收到回电时都能进行繁重的计算。

如果您确实还需要在一定时间后重新计算,您可以将AlarmManager to act as a timeout mechanism on each location update received (and cancel a previously set alarm) which would fire your heavy calculation method if there hasn't been a location update, using FusedLocationApi.getLastLocation()设置为当前位置的警报(如果您愿意,也可以使用缓存值)。

注意,FusedLocationProviderApi 还提供了一个 requestLocationupdates() method that takes a PendingIntent - this is perfect for background services which don't want or need to maintain a constantly running listener, but want to trigger a short running handler (which an IntentService 是完美的)响应事件。这确保您的应用程序将始终收到更新,即使应用程序被 Android.

停止也是如此。