doInBackground()android出错

时间:2014-04-08 11:06:40

标签: java android android-asynctask

我正在尝试从android活动(一个简单的登录表单)做一个http请求/响应但是在我完成代码后它给了我一个错误,因为我必须把它放在一个线程中,我不熟悉async任务,但我已经尝试实现它,但是,现在当我运行程序并点击提交它logcat给了我类似的东西

FATAL EXCEPTION: AsyncTask #1
Process: com.example.httpgetandroidexample, PID: 1131
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:300)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:841)
Caused by: android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6094)
at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:824)
at android.view.View.requestLayout(View.java:16431)
at android.view.View.requestLayout(View.java:16431)
at android.view.View.requestLayout(View.java:16431)
at android.view.View.requestLayout(View.java:16431)
at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:352)
at android.view.View.requestLayout(View.java:16431)
at android.widget.TextView.checkForRelayout(TextView.java:6600)
at android.widget.TextView.setText(TextView.java:3813)
at android.widget.TextView.setText(TextView.java:3671)
at android.widget.TextView.setText(TextView.java:3646)
at com.example.httpgetandroidexample.MainActivity$AsyncTaskRunner.doInBackground(MainActivity.java:87)
at com.example.httpgetandroidexample.MainActivity$AsyncTaskRunner.doInBackground(MainActivity.java:1)
at android.os.AsyncTask$2.call(AsyncTask.java:288)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
... 4 more

我不明白为什么!这是我的Android活动:

package com.example.httpgetandroidexample;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {

    public TextView content;
    EditText name,pass;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        name = (EditText)findViewById(R.id.name);
        pass = (EditText)findViewById(R.id.pass);
        content = (TextView)findViewById(R.id.text);

        Button button=(Button)findViewById(R.id.but);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                AsyncTaskRunner runner = new AsyncTaskRunner();
                runner.execute();
            }
        });


    }
    class AsyncTaskRunner extends AsyncTask<String, String, String> {

        private String resp;

        @Override
        protected String doInBackground(String... params) {
            publishProgress("Working..."); // Calls onProgressUpdate()
            try{ 

                // URLEncode user defined data

                String nameValue    = URLEncoder.encode(name.getText().toString(), "UTF-8");
                String passValue    = URLEncoder.encode(pass.getText().toString(), "UTF-8");

                // Create http cliient object to send request to server

                HttpClient Client = new DefaultHttpClient();

                // Create URL string

                String URL = "http://localhost:8080/login/web?user="+nameValue+"&pass="+passValue;

                //Log.i("httpget", URL);

                try
                {
                    String SetServerString = "";

                    // Create Request to server and get response

                    HttpGet httpget = new HttpGet(URL);
                    ResponseHandler<String> responseHandler = new BasicResponseHandler();
                    SetServerString = Client.execute(httpget, responseHandler);

                    // Show response on activity 

                    content.setText(SetServerString);
                }
                catch(Exception ex)
                {
                    content.setText("fail");
                    System.out.println(ex);
                    resp="fail";
                }
            }
            catch(UnsupportedEncodingException ex)
            {
                content.setText("FailAndroid!");
                resp="fail";
            } 
            return resp;
        }
        @Override
        protected void onPostExecute(String result) {
            content.setText(result);
        }
        protected void onPreExecute() {
        }

        @Override
        protected void onProgressUpdate(String... text) {
            content.setText(text[0]);

        }
    }
}

我的代码显示没有错误,甚至没有警告,但是当我按下提交按钮时,它会在“工作”消息出现后强行关闭,有人知道为什么? 提前谢谢

在你的帮助下(谢谢大家!)我修改了我的活动代码:

package com.example.httpgetandroidexample;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {

               public TextView content;
                EditText name,pass;

            @Override
            protected void onCreate(Bundle savedInstanceState) {

                      super.onCreate(savedInstanceState);
                     setContentView(R.layout.activity_main);

                     name      =  (EditText)findViewById(R.id.name);
                     pass       =  (EditText)findViewById(R.id.pass);
                     content       =  (TextView)findViewById(R.id.text);

                   Button button=(Button)findViewById(R.id.but);

                   button.setOnClickListener(new View.OnClickListener() {
                       @Override
                       public void onClick(View v) {
                        AsyncTaskRunner runner = new AsyncTaskRunner();
                        runner.execute();
                       }
                      });


   }
            class AsyncTaskRunner extends AsyncTask<String, String, String> {

              private String resp;

              @Override
              protected String doInBackground(String... params) {
               publishProgress("Working..."); // Calls onProgressUpdate()
              try{ 

                                     // URLEncode user defined data

                                       String nameValue    = URLEncoder.encode(name.getText().toString(), "UTF-8");
                                       String passValue    = URLEncoder.encode(pass.getText().toString(), "UTF-8");

                                    // Create http cliient object to send request to server

                                       HttpClient Client = new DefaultHttpClient();

                                    // Create URL string

                                     String URL = "http://localhost:8080/login/web?user="+nameValue+"&pass="+passValue;

                                    //Log.i("httpget", URL);

                                   try
                                    {
                                                  String SetServerString = "";

                                                // Create Request to server and get response

                                                  HttpGet httpget = new HttpGet(URL);
                                                 ResponseHandler<String> responseHandler = new BasicResponseHandler();
                                                 SetServerString = Client.execute(httpget, responseHandler);

                                                  // Show response on activity 

                                                return SetServerString;
                                     }
                                   catch(Exception ex)
                                      {
                                     Log.i("MyActivity","Exception");
                                       }
                                }
                              catch(UnsupportedEncodingException ex)
                               {

                                   Log.i("MyActivity","UnsupportedEncodingException");
                                } 
              return resp;
                            }
              @Override
              protected void onPostExecute(String result) {
               content.setText(result);
              }
              protected void onPreExecute() {
              }

              @Override
              protected void onProgressUpdate(String... text) {
               content.setText(text[0]);

              }
             }
}

但现在我收到了Log.i("MyActivity","Exception");消息,我仍然做错了什么?

更新

对于我的最后一次尝试,我再次按照一些在线教程修改了代码,这就是我所做的

package com.example.httpgetandroidexample;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.BasicResponseHandler;
import org.apache.http.impl.client.DefaultHttpClient;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {

               public TextView content;
                EditText name,pass;
                String URL;
            @Override
            protected void onCreate(Bundle savedInstanceState) {

                      super.onCreate(savedInstanceState);
                     setContentView(R.layout.activity_main);

                     name      =  (EditText)findViewById(R.id.name);
                     pass       =  (EditText)findViewById(R.id.pass);
                     content       =  (TextView)findViewById(R.id.text);

                   Button button=(Button)findViewById(R.id.but);
                   try {
                    String nameValue    = URLEncoder.encode(name.getText().toString(), "UTF-8");
                       String passValue    = URLEncoder.encode(pass.getText().toString(), "UTF-8");
                       URL = "http://localhost:8080/login/web?user="+nameValue+"&pass="+passValue;
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }

                   button.setOnClickListener(new View.OnClickListener() {
                       @Override
                       public void onClick(View v) {
                        AsyncTaskRunner runner = new AsyncTaskRunner();
                        runner.execute(new String[ ] { URL });
                       }
                      });


   }
            private class AsyncTaskRunner extends AsyncTask<String, Void, String> {


                @Override
                protected String doInBackground(String... urls) {
                  String response = "";
                  for (String url : urls) {
                    DefaultHttpClient client = new DefaultHttpClient();
                    HttpGet httpGet = new HttpGet(url);
                    try {
                      HttpResponse execute = client.execute(httpGet);
                      InputStream content = execute.getEntity().getContent();

                      BufferedReader buffer = new BufferedReader(new InputStreamReader(content));
                      String s = "";
                      while ((s = buffer.readLine()) != null) {
                        response += s;
                      }

                    } catch (Exception e) {
                      e.printStackTrace();
                    }
                  }
                  return response;
                }

                @Override
                protected void onPostExecute(String result) {
                  content.setText(result);
                }
              }
}

这里的logcat是详细模式:

Permission denied (missing INTERNET permission?)
at java.net.InetAddress.lookupHostByName(InetAddress.java:418)
at java.net.InetAddress.getAllByNameImpl(InetAddress.java:236)
at java.net.InetAddress.getAllByName(InetAddress.java:214)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:137)
at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
at com.example.httpgetandroidexample.MainActivity$AsyncTaskRunner.doInBackground(MainActivity.java:69)
at com.example.httpgetandroidexample.MainActivity$AsyncTaskRunner.doInBackground(MainActivity.java:1)
at android.os.AsyncTask$2.call(AsyncTask.java:288)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:841)
Caused by: libcore.io.GaiException: getaddrinfo failed: EAI_NODATA (No address associated with hostname)
at libcore.io.Posix.getaddrinfo(Native Method)
at libcore.io.ForwardingOs.getaddrinfo(ForwardingOs.java:61)
at java.net.InetAddress.lookupHostByName(InetAddress.java:405)
... 17 more
Caused by: libcore.io.ErrnoException: getaddrinfo failed: EACCES (Permission denied)
... 20 more

从我理解的是它缺少许可,但问题是我在我的清单文件中有它:

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" android:permission="android.permission.INTERNET">

5 个答案:

答案 0 :(得分:5)

Logcat错误:

引起:android.view.ViewRootImpl $ CalledFromWrongThreadException:只有创建视图层次结构的原始线程才能触及其视图。

您尝试使用doInBackground中的UI线程,

content.setText("fail");

你无法通过后台线程使用onPostExecute触摸ui线程中的任何内容来处理UI

这是你想要的一个样本。

 private class DownloadWebPageTask extends AsyncTask<String, Void, String> {
    @Override
    protected String doInBackground(String... urls) {
      String response = "";
      for (String url : urls) {
        DefaultHttpClient client = new DefaultHttpClient();
        HttpGet httpGet = new HttpGet(url);
        try {
          HttpResponse execute = client.execute(httpGet);
          InputStream content = execute.getEntity().getContent();

          BufferedReader buffer = new BufferedReader(new InputStreamReader(content));
          String s = "";
          while ((s = buffer.readLine()) != null) {
            response += s;
          }

        } catch (Exception e) {
          e.printStackTrace();
        }
      }
      return response;
    }

    @Override
    protected void onPostExecute(String result) {
      textView.setText(result);
    }
  }

您需要从doInBackground

返回字符串

样本中:return response;

表示您需要更改:

样本:

1- AsyncTask<String, Void, String>&lt; ---最后一个值是doInBackground

protected String doInBackground更多信息的内容

2- return response;&lt; ---将返回类型更改为String

3 - 返回您的值protected void onPostExecute(String result)

4- onPostExecute&lt; ---这也必须是String

然后使用onPostExecute(String result)

中的用户界面 示例6.5. Example: AsyncTask中的

&lt; ---结果是您的字符串

来自This site String nameValue = URLEncoder.encode(name.getText().toString(), "UTF-8"); String passValue = URLEncoder.encode(pass.getText().toString(), "UTF-8");

的代码

<强>更新

您再次使用UI:

doInBackground

如果您想要这个值,您可以将它们发送到asynctask的构造函数或作为参数发送到catch(UnsupportedEncodingException ex) { ex.printStackTrace(); } ,我推荐第二种方式

作为您在try catch语句中的代码,您的应用程序未关闭,因为您不打印任何对catch有用的东西,如果您使用catch它更合适打印错误太像:

android:permission="android.permission.INTERNET">

更新2

您在代码中声明您的Android权限如下:

<manifest xlmns:android...>
 ...
 <uses-permission android:name="android.permission.INTERNET"></uses-permission>
</manifest>

但您必须添加以下权限:

<?xml version="1.0" encoding="utf-8"?>
<manifest  
    ......
    ......
    .....>

<uses-sdk
    ...... />

<uses-permission android:name="android.permission.INTERNET" />

<application
     .......
     .......
</application>

</manifest>

你的清单必须像:

{{1}}

答案 1 :(得分:1)

  

引起:android.view.ViewRootImpl $ CalledFromWrongThreadException:   只有创建视图层次结构的原始线程才能触及它   视图。

stacktrace说你正在从一个错误的背景线程中更新ui。

你有

content.setText(SetServerString);

您正在更新doInbackground中的错误。

您只能从ui线程更新ui。在后台线程上调用doInBackground。在ui线程上调用onPostExecute。因此,您可以doInBackgorund返回并在onPostExecute更新ui。

检查主题 4个步骤 @

http://developer.android.com/reference/android/os/AsyncTask.html

而不是System.out.println(ex);使用Log来记录信息。

http://developer.android.com/reference/android/util/Log.html

答案 2 :(得分:1)

您无法在doInBackground中使用UI!每当您的代码进入 doInBackground 中的content.setText()时,它都会崩溃。

答案 3 :(得分:1)

content.setText();中的{p> doInbackground正在犯错误。您无法更新doInbackground中的用户界面。任何更改用户界面的内容都应移至onPostExecute

答案 4 :(得分:1)

用户界面上的所有修改(用户看到的任何内容,如Buttons或TextFields)必须由主线程(UI线程)执行。 doInBackground()方法中的代码在不同的线程上运行。因此,您应该在此处下载数据(这是耗时的计算),然后使用onPostExecute()方法中的查询信息更改UI。