android - 调用 Looper.quit() 时崩溃

标签 android

我有一个连接到 Web 服务的 Android IntentService 以下载一些 json 格式的作业。然后将这些解析并放入 SQLite3 数据库中。

以下代码(添加了敏感位)在模拟器上运行但从未在实际设备上运行。

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");
    }
}

它提示发布到死线程。在阅读了一些内容之后,我添加了一个 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(代码=1)

如果我删除对 quit() 的调用,则不会发生崩溃,但显然服务不会停止并释放资源,直到应用程序退出。

我做错了什么?

最佳答案

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
}

关于android - 调用 Looper.quit() 时崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33651871/

相关文章:

android - WebView 点击打开手机浏览器

java - 比 WifiManager startScan() 更快的 WiFi 扫描替代方案?

javascript - 有什么方法可以在 native react 中选择突出显示pdf文件中的文本

java - 在后台运行线程

java - 如何使用我的 Android 应用程序使用 JSON 将参数发送到远程服务器。代码如下

android - 合并 PullToRefresh 和 SwipeListView 库时出现了一些错误

java - Ant 无法导入 R.java

需要 Android XPath 帮助

android - genymotion 版本和虚拟设备版本不匹配

java - 在输入 Android 时动态搜索