DefaultHttpClient到AndroidHttpClient

Lar*_*ara 26 android apache-commons-httpclient

我的代码有问题,我希望得到一些帮助.我是第一次使用这段代码:

        new DefaultHttpClient().execute(new HttpGet(linkk)).getEntity().writeTo(
           new FileOutputStream(f));
Run Code Online (Sandbox Code Playgroud)

它在Android 2.3上运行得很好但在4.0上却没有.经过一些研究,我听说使用AndroidHttpClient更好,这样它就可以在4.0和3.1上运行.问题是我不知道我是否正确修改了我的代码,而且互联网上没有太多关于AndroidhttpClient的例子.

这是我调整后的代码:

    AndroidHttpClient client = AndroidHttpClient.newInstance("Android");
    HttpGet request = new HttpGet(linkk);   
    HttpResponse response = client.execute(request); //here is where the exception is thrown    
    response.getEntity().writeTo(new FileOutputStream(f));
Run Code Online (Sandbox Code Playgroud)

这是logcat显示的内容:

     01-03 01:32:11.950: W/dalvikvm(17991): threadid=1: thread exiting with uncaught exception (group=0x40a2e1f8)
     01-03 01:32:11.986: E/AndroidRuntime(17991): FATAL EXCEPTION: main
     01-03 01:32:11.986: E/AndroidRuntime(17991): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.lacra.fbirthdays/com.lacra.fbirthdays.ListV}: android.os.NetworkOnMainThreadException
     01-03 01:32:11.986: E/AndroidRuntime(17991):   at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1956)
     01-03 01:32:11.986: E/AndroidRuntime(17991):   at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
     01-03 01:32:11.986: E/AndroidRuntime(17991):   at android.app.ActivityThread.access$600(ActivityThread.java:123)
     01-03 01:32:11.986: E/AndroidRuntime(17991):   at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
     01-03 01:32:11.986: E/AndroidRuntime(17991):   at android.os.Handler.dispatchMessage(Handler.java:99)
     01-03 01:32:11.986: E/AndroidRuntime(17991):   at android.os.Looper.loop(Looper.java:137)
     01-03 01:32:11.986: E/AndroidRuntime(17991):   at android.app.ActivityThread.main(ActivityThread.java:4424)
     01-03 01:32:11.986: E/AndroidRuntime(17991):   at java.lang.reflect.Method.invokeNative(Native Method)
     01-03 01:32:11.986: E/AndroidRuntime(17991):   at java.lang.reflect.Method.invoke(Method.java:511)
    01-03 01:32:11.986: E/AndroidRuntime(17991):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
    01-03 01:32:11.986: E/AndroidRuntime(17991):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
    01-03 01:32:11.986: E/AndroidRuntime(17991):    at dalvik.system.NativeStart.main(Native Method)
    01-03 01:32:11.986: E/AndroidRuntime(17991): Caused by: android.os.NetworkOnMainThreadException
    01-03 01:32:11.986: E/AndroidRuntime(17991):    at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1099)
    01-03 01:32:11.986: E/AndroidRuntime(17991):    at java.net.InetAddress.lookupHostByName(InetAddress.java:391)
    01-03 01:32:11.986: E/AndroidRuntime(17991):    at java.net.InetAddress.getAllByNameImpl(InetAddress.java:242)
    01-03 01:32:11.986: E/AndroidRuntime(17991):    at java.net.InetAddress.getAllByName(InetAddress.java:220)
    01-03 01:32:11.986: E/AndroidRuntime(17991):    at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:137)
    01-03 01:32:11.986: E/AndroidRuntime(17991):    at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
    01-03 01:32:11.986: E/AndroidRuntime(17991):    at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
    01-03 01:32:11.986: E/AndroidRuntime(17991):    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360)
    01-03 01:32:11.986: E/AndroidRuntime(17991):    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
Run Code Online (Sandbox Code Playgroud)

yor*_*rkw 72

自API级别9以来引入了StrictMode.ThreadPolicy,并且自API级别11以来默认的线程策略已经更改,简而言之,不允许在UI线程上执行网络操作(包括HttpClient和HttpUrlConnection).如果你这样做,你得到NetworkOnMainThreadException.

可以使用以下方法更改此限制:

    if (android.os.Build.VERSION.SDK_INT > 9) {
      StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
      StrictMode.setThreadPolicy(policy);
    }
Run Code Online (Sandbox Code Playgroud)

将上面的代码添加到主活动的onCreate()方法中.

此外,始终建议将网络操作从UI线程移开,例如,使用AsyncTask.

希望这个帮助.

  • 这些政策的重点是强制实践,并确保您的应用程序运行良好.关闭政策是个坏主意.请参阅Sbossb对正确方法的回答. (9认同)
  • @rgardler,仔细阅读答案:**总是建议将网络操作从UI线程移开,例如,使用AsyncTask.**线程策略没有突出显示而且很多消费者开发者都没有意识到,值得指点找出相同代码在GingerBread中运行的确切原因,但也不是HoneyComb,同时请注意AsyncTask是推荐的,但绝对不是唯一正确的方法. (4认同)
  • @yorkw呃......你为什么要把这个作为答案?!?寻求快速修复的初学者不会关心...他们只是将您的代码复制并粘贴到他们的项目中,当另一个糟糕的应用程序在Android Market上发布时,这将是您的错. (2认同)

Ste*_*aly 32

使用AsyncTask,以便网络请求不会阻止UI线程.该NetworkOnMainThreadException因为API版本11,这就是为什么它是只显示了3.0和最多的原因进行了介绍.

private class NetworkTask extends AsyncTask<String, Void, HttpResponse> {
    @Override
    protected HttpResponse doInBackground(String... params) {
        String link = params[0];
        HttpGet request = new HttpGet(link);
        AndroidHttpClient client = AndroidHttpClient.newInstance("Android");
        try {
            return client.execute(request);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        } finally {
        client.close();
    }
    }

    @Override
    protected void onPostExecute(HttpResponse result) {
        //Do something with result
        if (result != null)
            result.getEntity().writeTo(new FileOutputStream(f));
    }
}
Run Code Online (Sandbox Code Playgroud)

要调用此线程,请执行此操作.

new NetworkTask().execute(linkk);
Run Code Online (Sandbox Code Playgroud)

看一下Android开发者网站上写的这篇文章.它更详细地解释了如何编写应用程序来处理线程.