我有一个服务,我用它来发送SOAP Webservice调用。一切都很完美,它永远不会崩溃,但我认为应该这样。
我的问题是,当我长时间运行查询(10-50秒)时,在我的workerthread完成之前调用onDestroy()(我调用stopSelfResult)。是不是在LogCat窗口中没有立即执行System.out.println /不同步(缓存)?
是通过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);
};
}
我的WebService类
public class WebService extends Service {
public static final int WS_RT_BLOOSOAP = 0;
public static final int WS_RT_RSS = 1;
public static final int WS_RESULT_OK = 0;
public static final int WS_RESULT_UNABLE_TO_CONNECT = 2;
public static final int WS_RESULT_INVALID_REQUEST = 3;
public static final int WS_RESULT_UNKNOWN_ERROR = 999;
static private SparseBooleanArray workList=null; // Only one job with the same frameID is allowed to run
@Override
public void onCreate() {
System.out.println("#### WebService onCreate");
if (workList==null) workList = new SparseBooleanArray();
}
@Override
public void onDestroy() {
System.out.println("#### WebService onDestroy");
}
/***************************************************************************
* Start working
**************************************************************************/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
System.out.println("WebService Start ID=" + startId);
final int currentID = startId;
final Intent currentIntent = intent;
Runnable workerRunnable = new Runnable() {
public void run() {
System.out.println("WebService Thread Start - ID=" + currentID);
int resultCode;
Bundle responseExtras = new Bundle();
resultCode = serverRequest(currentIntent,responseExtras);
sendResponse(currentIntent,resultCode,responseExtras);
System.out.println("WebService Thread End - ID=" + currentID);
Bundle extras = currentIntent.getExtras();
if (extras != null) {
int frameID = extras.getInt("FRAMEID");
System.out.println(">>>>>>> PUT FALSE " + frameID);
workList.put(frameID, false);
};
stopSelfResult(currentID);
}
};
if (intent!=null) {
Bundle extras = intent.getExtras();
if (extras != null) {
int frameID = extras.getInt("FRAMEID");
Boolean found = workList.get(frameID,false);
if (!found) {
System.out.println(">>>>>>> PUT TRUE FRAMEID=" + frameID);
workList.put(frameID, true);
Thread workerThread = new Thread(workerRunnable);
workerThread.start();
} else {
System.out.println(">>>>>>> Allready running FRAMEID=" + frameID);
}
};
};
return Service.START_STICKY;
};
/***************************************************************************
* No binding
**************************************************************************/
@Override
public IBinder onBind(Intent intent) {
return null;
}
/***************************************************************************
* Send webservice request and return result in responseExtras
**************************************************************************/
private int serverRequest(Intent intent, Bundle responseExtras) {
...
};
/***************************************************************************
* Send response back to service caller using Messenger.send()
**************************************************************************/
private boolean sendResponse(Intent intent, int resultCode, Bundle responseExtras) {
...
};
答案 0 :(得分:0)
不幸的是,它总会发生。实际上,默认情况下,android应用程序组件的生命周期与任何类型的工作线程都不同步。
因此,您可能需要手动检查服务的状态,例如,您可以使用一个布尔标志来指示服务是否正常工作。另一个方便的方法是使用IntentService而不是使用普通服务,它自己处理工作线程和生命周期功能。
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.
}
}
答案 1 :(得分:0)
如果您使用最新的stopSelfResult()
致电startId
,您的服务就会停止。因此,如果服务以startId = 1的意图开始,另一个意图使用startId = 2而第二个意图在第一个意图之前完成,则在完成startId = 1之前调用stopSelfResult(2)
。如果使用最新的startId调用stopSelfResult()
并且没有其他意图待处理,该服务会立即被销毁。
持有最新的startId。添加要在数组中处理的所有startIds(例如List<Integer> runningStartIds
),并在完成处理后将其删除。在完成删除后,将当前startId与最新的startId进行比较,如果runningStartIds不为空,则执行不调用stopSelfResult()
。因此,当最后的startId处理完所有意图并且没有其他意图待处理时,你最终只会调用stopSelfResult()
。
应该有用,虽然我还没有发布一个例子。
.: EDIT :.
Explenation:
无论您在后台做什么,下一个Intent
都可以从onStartCommand()
返回的速度尽快进入。
.: EDIT :.
不是改进(改进:
考虑到这一点,实际上你只需保留mLastStartId
。只需跳过调用stopSelfResult()
,直到完成的startId与mLastStartId
匹配。)