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