【问题标题】:Custom service class with a ThreadPoolExecutor killed when app is off当应用程序关闭时,带有 ThreadPoolExecutor 的自定义服务类被终止
【发布时间】:2016-12-23 02:28:25
【问题描述】:

我需要在自定义服务中并行执行多个任务才能使这些工作正常运行:
- 位置服务和活动识别 API。
- 地理围栏 API 和 REST API 调用。

我是 java 和 android 线程的新手,我发现实现这一点的最佳方法是使用 ThreadPoolExecutor 而不是创建自己的线程类并处理所有 Handler Looper 的东西。

当我执行我的应用程序时,服务启动,位置更新和活动更新在线程内正常工作。但是,当我关闭应用程序时,服务重新启动(当return START_STICKY;)并且线程不再工作。当(return START_NOT_STICKY;)时,服务消失。 (就我而言,我不能使用 startforeground())

我正在使用这个库 (smart-location-lib) 来更新位置和活动。

- 这是我的自定义服务代码:

public class LocationService extends Service {

    private ThreadPoolExecutor mDecodeThreadPool;
    private BlockingQueue<Runnable> mDecodeWorkQueue;

    private int NUMBER_OF_CORES = Runtime.getRuntime().availableProcessors();
    private final int KEEP_ALIVE_TIME = 1;
    private final TimeUnit KEEP_ALIVE_TIME_UNIT = TimeUnit.SECONDS;

    public LocationService () {
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Toast.makeText(this, "Location services created", Toast.LENGTH_SHORT).show();
        mDecodeWorkQueue = new LinkedBlockingQueue<Runnable>();
        mDecodeThreadPool = new ThreadPoolExecutor(
                NUMBER_OF_CORES * 2, // Initial pool size
                NUMBER_OF_CORES * 2, // Max pool size
                KEEP_ALIVE_TIME,
                KEEP_ALIVE_TIME_UNIT,
                mDecodeWorkQueue);    
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Toast.makeText(this, "Location services started", Toast.LENGTH_SHORT).show();
        mDecodeThreadPool.execute(new LocationRunnable(getApplicationContext()));
        return START_STICKY;
    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();
        Log.v("LOW MEMORY", "|||||||||||||||||||||||||||||||||||||");

    }

    @Override
    public IBinder onBind(Intent intent) {
        throw new UnsupportedOperationException("Not yet implemented");
    }


    @Override
    public void onDestroy() {
        Toast.makeText(this, "Location services stopped", Toast.LENGTH_LONG).show();
        mDecodeThreadPool.shutdown();
        mDecodeThreadPool.shutdownNow();
        super.onDestroy();
    }
}

- 这是我的 Runnable 类代码:

public class LocationRunnable implements Runnable, OnLocationUpdatedListener, OnActivityUpdatedListener {

     SmartLocation smartLocation;
     public LocationRunnable(Context ctx) {
          smartLocation = new SmartLocation.Builder(ctx).logging(true).build();

     }

    @Override
    public void run() {
        Log.v("THREAD", "THREAD STARTED");
        startLocation();
     }


    private void startLocation() {
        smartLocation.location().start(this);
        smartLocation.activity().start(this);
    }

    @Override
    public void onActivityUpdated(DetectedActivity detectedActivity) {
        if (detectedActivity != null) {
            Log.v("ACTIVITY", "ACTIVITY UPDATED");
        } else {
            Log.v("ACTIVITY", "NULL");
        }

    }
    int i = 0;
    @Override
    public void onLocationUpdated(Location location) {
        Log.v("LOCATION", "LOCATION UPDATED" + i++);
    }

    private String getNameFromType(DetectedActivity activityType) {
        switch (activityType.getType()) {
            case DetectedActivity.IN_VEHICLE:
                return "in_vehicle";
            case DetectedActivity.ON_BICYCLE:
                return "on_bicycle";
            case DetectedActivity.ON_FOOT:
                return "on_foot";
            case DetectedActivity.STILL:
                return "still";
            case DetectedActivity.TILTING:
                return "tilting";
            default:
                return "unknown";
        }
    }

}

我不确定这是否是获得我需要的正确或最佳方式。
非常感谢任何帮助!

【问题讨论】:

  • 您不会在 Android 中“关闭应用程序”。请准确解释您所说的“关闭应用程序”是什么意思。
  • 这只是多任务按钮(显示打开的应用程序的按钮)。所以,我把它刷掉,它应该继续在后台运行。
  • 终止后台进程,就好像进程因内存不足而终止一样。
  • 是的,但是当服务重新启动时(返回 START_STICKY;),位置更新不再起作用。
  • 我不知道“位置更新不再起作用”的确切含义。您将需要再次设置位置更新,这在您的问题中没有的代码中。您的进程可以随时终止,即使使用服务也是如此,因此这是您的应用需要能够处理的场景。

标签: android multithreading locationlistener threadpoolexecutor background-service


【解决方案1】:

我知道这个问题很老了,但它可能对其他人有帮助。

我认为这是由于 Runnable.run() 中的代码立即退出,从而结束父线程,因此位置的更改不再有要发布的对象。

smartLocation.location().start(this); // 这个

您在重新启动之前得到更新的原因可能是由于垃圾收集没有清除不再使用的 Runnable 对象或代码中对它的一些现有引用。

【讨论】:

    猜你喜欢
    • 2017-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多