Android服务在workerthread结束前调用onDestroy

Android服务在workerthread结束前调用onDestroy,android,service,ondestroy,Android,Service,Ondestroy,我有一个用于发送SOAP Web服务调用的服务。一切都很完美,从来没有崩溃过,但我觉得应该 我的问题是,当我有10-50秒的长时间运行查询时。onDestroy在workerthread完成之前被调用,我调用stopSelfResult。可能是System.out.println没有立即执行/在LogCat窗口中缓存不同步 下面是如何通过QueryBase类启动服务: QueryBase someService = new QueryBase(myActivity); someService.

我有一个用于发送SOAP Web服务调用的服务。一切都很完美,从来没有崩溃过,但我觉得应该

我的问题是,当我有10-50秒的长时间运行查询时。onDestroy在workerthread完成之前被调用,我调用stopSelfResult。可能是System.out.println没有立即执行/在LogCat窗口中缓存不同步

下面是如何通过QueryBase类启动服务:

QueryBase someService  = new QueryBase(myActivity);
someService.execute(...);
我的QueryBase类

public class QueryBase {

private WeakReference<Activity> currentActivity = null;

private static class ResponseHandler extends Handler {
    private QueryBase mQueryBase;

    public ResponseHandler(QueryBase vQueryBase) {
        mQueryBase = vQueryBase;
    };

    public void handleMessage(Message message) {
        Bundle extras = message.getData();

        mQueryBase.handleResult(message.arg1,message.arg2,extras.getInt("FRAMEID"),extras.getString("RESPONSE"));
        mQueryBase=null;
    };
};

public QueryBase(Activity vActivity) {
    currentActivity = new WeakReference<Activity>(vActivity);
}

/***************************************************************************
 * Start the service
 **************************************************************************/
public boolean execute(Activity vActivity, int cmdID, int frameID, String serverAddress, int requestType, String request) {

    // Valid activity
    if (vActivity==null) return false;

    // Test to see if network is connected
    if (!isOnline(vActivity)) return false;

    Intent webService                           = new Intent(vActivity, WebService.class);
    final ResponseHandler responseHD        = new ResponseHandler(this);
    Messenger messenger                     = new Messenger(responseHD);

    webService.putExtra("QUERYRESULT_MESSENGER",messenger);
    webService.putExtra("CMDID", cmdID);
    webService.putExtra("FRAMEID",frameID);
    webService.putExtra("SERVER_ADDRESS",serverAddress);
    webService.putExtra("REQUEST_TYPE",requestType);
    webService.putExtra("REQUEST",request);

    vActivity.startService(webService);     

    return true;
}

/***************************************************************************
 * Is my Android connected?
 **************************************************************************/
private Boolean isOnline(Activity vActivity) {
    ConnectivityManager connMgr = (ConnectivityManager) vActivity.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
    if (networkInfo != null && networkInfo.isConnected()) return true;
    else return false;
}

/***************************************************************************
 * Get current Activity
 **************************************************************************/
public Activity getCurrentActivity() {
    Activity ac = currentActivity.get();
    if (ac!=null) {
        if ((ac.isFinishing()) || (ac.activityDestroyed)) {
            return null;
        };
    }
    return ac;
};

/***************************************************************************
 * XML result from webservice
 **************************************************************************/
public void handleResult(int resultCode, int cmdID, int frameID, String response) {
    System.out.println("DEFAULT HANDLER: ResultCode: " + resultCode);
};

}

不幸的是,它总是可能发生的。实际上,android应用程序组件的生命周期并不同步,默认情况下不同步任何类型的工作线程

因此,您可能需要手动检查服务的状态,例如,您可以使用一个布尔标志来指示服务是否正在工作。另一个方便的方法是使用,而不是使用普通的服务,它自己处理工作线程和生命周期特性

public class MyIntentService extends IntentService {
    public MyIntentService() {
        super("MyIntentService ");
    }
    @Override
    protected void onHandleIntent(Intent intent) {
        // This callback-method is called inside worker thread, 
        // so you can do some long-time network job here.
        SystemClock.sleep(30000); // 30 seconds
        // In this timing the service will be stopped automatically.
    }
}    

如果您使用最新的startId调用stopSelfResult,您的服务将停止。因此,如果服务以startId=1的意图启动,而另一个意图以startId=2启动,并且第二个意图在第一个意图之前完成,则在startId=1完成之前调用stopSelfResult2。如果您使用最新的startId调用stopSelfResult,并且没有其他未完成的意图,则服务将立即被销毁

举行最新的startId。在一个数组中添加您希望处理的所有StartID,例如列出运行StartID,并在完成处理后将其删除。完成删除后,将当前startId与最新的startId进行比较,如果RunningStartId不为空,则不要调用stopSelfResult。因此,您将只为最新的startId调用stopSelfResult,此时所有意图都已处理,不再有意图挂起

虽然我还没有发布一个例子,但应该是可行的

:编辑:。 解释: 无论您在后台做什么,下一个意图可能会在您从onStartCommand返回时出现

:编辑:。 不是改进:
考虑到这一点,事实上你只需要保留mLastStartId。只要跳过调用stopSelfResult,直到完成的startId与mLastStartId匹配。

我不想使用IntentService,因为每个请求/意图都是使用一个工作线程工作队列依次执行的。基本思想是启动例如3个soap请求,当结果返回时,我可以在3个视图中的一个视图中显示。如果我使用IntentService,如果第一个请求连接到速度较慢的服务器,则请求2和3将等待很长时间。我不确定我是否理解您使用标志来指示服务是否工作的意思。你是说我无法避免在工作线程结束之前调用onDestroy吗?我不明白为什么Android在a我的活动在前面运行,b我的工作线程在运行时调用它。这不是服务在后台运行的基本理念,通常在我的活动中应该有更长的生命周期,Android资源耗尽时除外。如果不是的话,你怎么能制作一个能在背景中持续播放的音乐播放器呢?太棒了。我没想过,但这很有道理。谢谢。关于你的进步。我不确定这会改变什么。在我看来,如果finished startId=2,mLastStartID=2,startId=1的运行时间比startId=2的运行时间长,问题也会一样?使用引用计数器AtomicInteger,然后在引用计数器达到0时调用startId最高的stopSelfResult如何?你说得对。我的进步是错误的。一个参考计数器也应该做这项工作。
public class MyIntentService extends IntentService {
    public MyIntentService() {
        super("MyIntentService ");
    }
    @Override
    protected void onHandleIntent(Intent intent) {
        // This callback-method is called inside worker thread, 
        // so you can do some long-time network job here.
        SystemClock.sleep(30000); // 30 seconds
        // In this timing the service will be stopped automatically.
    }
}