2015-11-11 6 views
1

У меня есть Android IntentService, который подключается к веб-службе для загрузки некоторых заданий в формате json. Затем они разбираются и помещаются в базу данных SQLite3.Сбой при вызове Looper.quit()

Следующий код (с добавленными чувствительными битами) работал на эмуляторе, но никогда не работал на самом устройстве.

public class FetchJobsService extends IntentService { 
    private final static String LOG_TAG = "FetchJobsService"; 

    public FetchJobsService() { 
     super("FetchJobsService"); 
    } 

    @Override 
    protected void onHandleIntent(Intent intent) { 
     Log.i(LOG_TAG, "Fetch Jobs Service Started"); 

     AsyncHttpClient client = new AsyncHttpClient(); 

     Map<String, Object> params = new HashMap<String, Object>(); 
     // Add params to send in the request! 
     JSONObject jsonData = new JSONObject(params); 

     RequestParams requestParams = new RequestParams(); 
     requestParams.put(Constants.DATA, jsonData.toString()); 


     client.post(Constants.FETCH_JOBS, requestParams, 
      new AsyncHttpResponseHandler() { 
       @Override 
       public void onSuccess(int i, Header[] headers, byte[] bytes) { 
        try { 
         JSONObject returnObj = new JSONObject(new String(bytes)); 
         Log.i(LOG_TAG, "Success! Jobs downloaded"); 
         JSONObject dataObj = returnObj.getJSONObject(Constants.DATA); 
         JSONArray jobs = dataObj.getJSONArray(Constants.JOBS); 
         // Do something with the data downloaded! 
        } catch (JSONException e) { 
         Log.e(LOG_TAG, "Failure! Jobs not successfully downloaded", e); 
        } 
       } 

       @Override 
       public void onFailure(int statusCode, Header[] headers, byte[] bytes, 
             Throwable throwable) { 
        Log.i(LOG_TAG, "Failure! Status Code: " + statusCode); 
       } 
      } 
     ); 

     Log.i(LOG_TAG, "Fetch Jobs Service Finished"); 
    } 
} 

Он жаловался на публикацию в Dead Thread. После некоторого чтения вокруг, я добавил Looper держать IntentService вокруг, пока данные не были загружены и обработаны, как таковой:

public class FetchJobsService extends IntentService { 
    private final static String LOG_TAG = "FetchJobsService"; 

    public FetchJobsService() { 
     super("FetchJobsService"); 
    } 

    @Override 
    protected void onHandleIntent(Intent intent) { 
     Log.i(LOG_TAG, "Fetch Jobs Service Started"); 

     if (Looper.myLooper() == null) { 
      Looper.prepare(); 
     } 

     AsyncHttpClient client = new AsyncHttpClient(); 

     Map<String, Object> params = new HashMap<String, Object>(); 
     // Add params to send in the request! 
     JSONObject jsonData = new JSONObject(params); 

     RequestParams requestParams = new RequestParams(); 
     requestParams.put(Constants.DATA, jsonData.toString()); 


     client.post(Constants.FETCH_JOBS, requestParams, 
      new AsyncHttpResponseHandler() { 
       @Override 
       public void onSuccess(int i, Header[] headers, byte[] bytes) { 
        try { 
         JSONObject returnObj = new JSONObject(new String(bytes)); 
         Log.i(LOG_TAG, "Success! Jobs downloaded"); 
         JSONObject dataObj = returnObj.getJSONObject(Constants.DATA); 
         JSONArray jobs = dataObj.getJSONArray(Constants.JOBS); 
         // Do something with the data downloaded! 
        } catch (JSONException e) { 
         Log.e(LOG_TAG, "Failure! Jobs not successfully downloaded", e); 
        } finally { 
         if (Looper.myLooper() != null) { 
          Looper.myLooper().quit(); 
         } 
        } 
       } 

       @Override 
       public void onFailure(int statusCode, Header[] headers, byte[] bytes, 
             Throwable throwable) { 
        Log.i(LOG_TAG, "Failure! Status Code: " + statusCode); 
        if (Looper.myLooper() != null) { 
         Looper.myLooper().quit(); 
        } 
       } 
      } 
     ); 


     Looper.loop(); 
     Log.i(LOG_TAG, "Fetch Jobs Service Finished"); 
    } 
} 

Задания теперь загружены успешно, однако вызов quit() или quitSafely() вызывает сбой Fatal signal 11 (SIGSEGV) at 0x0000000c (code=1) ,

Если я удаляю вызовы quit(), то нет сбоя, но, очевидно, служба не останавливается и не освобождает ресурсы, пока приложение не завершит работу.

Что я делаю неправильно?

ответ

1

IntentService предназначен для обработки собственного жизненного цикла. Вы просто переопределяете обратный вызов onHandleIntent и выполняете то, что вам нужно сделать - как только этот метод выйдет из IntentService, он закроется.

IntentService уже работает в отдельном потоке, поэтому не имеет смысла делать запрос асинхронно. Синхронно выполнять сетевой вызов в обратном вызове onHandleIntent. Есть несколько примеров в this article.

Вы могли бы попробовать что-то вдоль этих линий:

HttpEntity requestEntity = new UrlEncodedFormEntity(params); 

//set up post request 
final HttpPost post = new HttpPost(url); 
post.addHeader(requestEntity.getContentType()); 
post.setEntity(requestEntity); 

//get http client 
DefaultHttpClient mHttpClient = new DefaultHttpClient(); 
final HttpParams httpParams = mHttpClient.getParams(); 
HttpConnectionParams.setConnectionTimeout(httpParams, TIMEOUT); 
HttpConnectionParams.setSoTimeout(httpParams, TIMEOUT); 
ConnManagerParams.setTimeout(httpParams, TIMEOUT); 

// get response -- this line will block until it is complete -- which is completely fine in an IntentService! 
HttpResponse response = getHttpClient().execute(post); 

int statusCode = response.getStatusLine().getStatusCode(); 
String responseEntity = EntityUtils.toString(response.getEntity()); 

if (statusCode != HttpStatus.SC_OK) { 
    // something bad happened, request failed! 
} else{ 
    // response was good, and "responseEntity" can be used for whatever you need 
} 
+0

Спасибо, у меня есть еще один звонок в WebService, которую я называю либо из пользовательского интерфейса или как часть описанного выше процесса. Каков наилучший способ приблизиться к этому? не следует ли повторно использовать код и написать его двумя способами? –

+0

Если вы загружаете и не заботитесь о ответе, проще всего использовать «IntentService». Если вы загружаете материал или хотите получить ответ, вы должны изучить 'ASyncTaskLoader' – JoeyJubb

Смежные вопросы