在Android的AsyncTask中使用HttpClient的FatalException

时间:2013-10-16 19:54:58

标签: java android android-asynctask

我在这里不知所措。我正在尝试使用从RESTful API中提取的数据在我的Activity中填充List。我已经使用Apache HttpClient库(org.apache.http.client)创建了与API(成功)对话的API层。但是,当我尝试将Activity与API层连接(通过AsyncTask)时,随之而来的是灾难。我从有问题的代码中删除了API层,而是嵌入了我能想到的最简单的例子来尝试隔离问题(无济于事)。这是有问题的代码:

public class MyActivity extends Activity {

@Override
protected void onCreate( Bundle savedInstanceState ) {

    super.onCreate( savedInstanceState );
    setContentView( R.layout.main );
}

@Override
protected void onResume() {

    super.onResume();
    new GetEventsTask().execute();
}

private class GetEventsTask extends AsyncTask<Object, Integer, List<IEvent>> {

    @Override
    protected List<IEvent> doInBackground( Object... params ) {

        fetch();
        return null;
    }

    @Override
    protected void onPostExecute( List<IEvent> events ) {

        Toast.makeText( getApplicationContext(), "Success", Toast.LENGTH_SHORT ).show();
    }

    private void fetch() {
        CloseableHttpClient client = HttpClients.createDefault();
        HttpPost httpPost = new HttpPost( "https://someurl.com/login" );

        List<NameValuePair> data = new ArrayList<NameValuePair>();
        data.add( new BasicNameValuePair( "username", "hai" ) );
        data.add( new BasicNameValuePair( "password", "kthxbye" ) );

        try {
            httpPost.setEntity( new UrlEncodedFormEntity( data ) );
            CloseableHttpResponse response = client.execute( httpPost );
        } catch( Exception e ) {
            Toast.makeText( getApplicationContext(), "Caught Exception", Toast.LENGTH_SHORT ).show();
        }
    }
}

这是堆栈跟踪:

10-16 19:36:04.264: ERROR/AndroidRuntime(633): FATAL EXCEPTION: AsyncTask #1
    java.lang.RuntimeException: An error occured while executing doInBackground()
    at android.os.AsyncTask$3.done(AsyncTask.java:200)
    at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:274)
    at java.util.concurrent.FutureTask.setException(FutureTask.java:125)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:308)
    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
    at java.lang.Thread.run(Thread.java:1019)
    Caused by: java.lang.ExceptionInInitializerError
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager$InternalConnectionFactory.<init>(PoolingHttpClientConnectionManager.java:487)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:147)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:136)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.<init>(PoolingHttpClientConnectionManager.java:112)
    at org.apache.http.impl.client.HttpClientBuilder.build(HttpClientBuilder.java:727)
    at org.apache.http.impl.client.HttpClients.createDefault(HttpClients.java:58)
    at ca.redacted.app.MyActivity$GetEventsTask.fetch(MyActivity.java:70)
    at ca.redacted.app.MyActivity$GetEventsTask.doInBackground(MyActivity.java:49)
    at ca.redacted.app.MyActivity$GetEventsTask.doInBackground(MyActivity.java:44)
    at android.os.AsyncTask$2.call(AsyncTask.java:185)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:306)
    ... 4 more
    Caused by: java.lang.ExceptionInInitializerError
    at org.apache.http.impl.conn.ManagedHttpClientConnectionFactory.<init>(ManagedHttpClientConnectionFactory.java:72)
    at org.apache.http.impl.conn.ManagedHttpClientConnectionFactory.<init>(ManagedHttpClientConnectionFactory.java:84)
    at org.apache.http.impl.conn.ManagedHttpClientConnectionFactory.<clinit>(ManagedHttpClientConnectionFactory.java:59)
    ... 15 more
    Caused by: java.lang.NoSuchFieldError: org.apache.http.message.BasicLineFormatter.INSTANCE
    at org.apache.http.impl.io.DefaultHttpRequestWriterFactory.<init>(DefaultHttpRequestWriterFactory.java:52)
    at org.apache.http.impl.io.DefaultHttpRequestWriterFactory.<init>(DefaultHttpRequestWriterFactory.java:56)
    at org.apache.http.impl.io.DefaultHttpRequestWriterFactory.<clinit>(DefaultHttpRequestWriterFactory.java:46)
    ... 18 more

我对Android编程比较陌生(并且暂时没有触及过Java),所以非常感谢任何帮助。

更新 基于调试运行,这是抛出FatalException

的行

CloseableHttpClient client = HttpClients.createDefault();

再次更新

切换到使用Android提供的DefaultHttpClient实现解决了问题(如果有其他人使用Apache版本遇到麻烦)。仍然不知道是什么让我对另一个图书馆感到悲伤。

2 个答案:

答案 0 :(得分:2)

我假设您已经添加了apache库,因为HttpClients不是Android代码中的内置版本,请参阅here。您之所以获得运行时异常而不是编译异常的原因我认为它是因为您的库不是不随应用程序导出。

ExceptionInInitializerError

表示无法加载指向此处的静态类(HttpClients):

CloseableHttpClient client = HttpClients.createDefault();

为了解决这个问题,您必须在eclipse:

中使用该应用程序导出外部apache库
  

项目 - &GT; config build path-&gt;选择要导出的lib。

除此之外,@ codeMagic指出你的catch子句不能使用Toast,因为它应该在UI线程上运行。这不会导致您的异常,因为您当前的代码没有到达try子句,而是一个抬头。

答案 1 :(得分:1)

从我看到的情况来看,这似乎不是你当前的问题,但在某些时候会出现问题。这些行

catch( Exception e ) {
        Toast.makeText( getApplicationContext(), "Caught Exception", Toast.LENGTH_SHORT ).show();

正在更新UI,因为它是从doInBackground()调用的,它正在后台Thread上运行,这将导致异常。处理此问题的方法是将response传递给onPostExecute()并根据您获得的回复类型从那里更新UI

According to the Java Documentation

此异常来自初始化static Class的问题。从这一行追溯

CloseableHttpClient client = HttpClients.createDefault();

并了解为何失败。