我试图让我的应用程序连接到我的服务器。但它会引发这些错误。如何修复MainThreadException?

时间:2013-04-03 03:03:13

标签: java android eclipse networkonmainthread

04-02 21:59:03.086: E/log_tag(27382): Error in http connection android.os.NetworkOnMainThreadException
04-02 21:59:03.106: E/log_tag(27382): Error converting result java.lang.NullPointerException
04-02 21:59:03.106: E/log_tag(27382): Error parsing data org.json.JSONException: End of input at character 0 of 

从以下代码:

package net.example.glutefree;

import android.app.Activity;
import android.os.Bundle;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.util.Log;
import android.widget.LinearLayout;
import android.widget.TextView;

public class Networking extends Activity {
    TextView txt;
    int request_Code = 1;
//called when activity is first created
    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_networking);
         // Create a crude view - this should really be set via the layout resources 
        // but since its an example saves declaring them in the XML. 
        LinearLayout rootLayout = new LinearLayout(getApplicationContext()); 
        txt = new TextView(getApplicationContext()); 
        rootLayout.addView(txt); 
        setContentView(rootLayout); 
        // Set the text and call the connect function. 
        txt.setText("Connecting...");
      //call the method to run the data retreival
        txt.setText(getServerData(KEY_121));
    }

    public static final String KEY_121 = "http://WEBSITE/application_query.php";

    private String getServerData(String returnString) {
       String UPC = getIntent().getStringExtra("UPCA");
       InputStream is = null;
       String result = "";
        //the upc data to send
        ArrayList<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();

        nameValuePairs.add(new BasicNameValuePair("UPCA",UPC));

        //http post
        try{

                HttpClient httpclient = new DefaultHttpClient();
                HttpPost httppost = new HttpPost(KEY_121);
                httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
                HttpResponse response = httpclient.execute(httppost);
                HttpEntity entity = response.getEntity();
                is = entity.getContent();

        } catch(Exception e) {
                Log.e("log_tag", "Error in http connection "+e.toString());
        }

        //convert response to string
        try {
                BufferedReader reader = new BufferedReader(new InputStreamReader(is,"iso-8859-1"),8);
                StringBuilder sb = new StringBuilder();
                String line = null;
                while ((line = reader.readLine()) != null) {
                        sb.append(line + "\n");
                }
                is.close();
                result=sb.toString();
        } catch(Exception e) {
                Log.e("log_tag", "Error converting result "+e.toString());
        }
        //parse json data
        try {
                JSONArray jArray = new JSONArray(result);
                Log.e("log_tag", "Result "+result.toString()); 
                for(int i=0;i<jArray.length();i++) {
                        JSONObject json_data = jArray.getJSONObject(i);
                        Log.i("log_tag","UPCA: "+json_data.getString("UPCA")+
                                ", Product: "+json_data.getString("Product"));
                        //Get an output to the screen
                        returnString += "\n\t" + jArray.getJSONObject(i);
                }
        } catch(JSONException e) {
                Log.e("log_tag", "Error parsing data "+e.toString());
        }
        return returnString;
    }   

}

6 个答案:

答案 0 :(得分:1)

使用

new Thread() {
    public void run() {
        final String data = getServerData(KEY_121);
        if (data != null)
            runOnUiThread(new Runnable()
            {
                public void run()
                {
                    txt.setText(data);
                }
            });
    }
}.start();

而不是:

 //call the method to run the data retreival
 txt.setText(getServerData(KEY_121));

您无法在主线程上运行长任务。但是你必须使用UI线程来设置文本。

答案 1 :(得分:0)

问题是您正在尝试从UI线程执行网络请求(getServerData())。为了避免ANR(例如,在缺乏网络连接或响应缓慢的情况下),不允许这样做。

有关如何为网络相关操作准备线程的信息,请参阅painless threading文章。然后,将需要网络操作的所有代码移动到单独的线程。

答案 2 :(得分:0)

Android不允许您在主(UI)线程上执行长时间运行的网络操作,因为这样做会导致整个UI锁定。您需要创建一个新线程来处理您的网络操作。我建议创建一个AsyncTask,您可以通过调用

从主线程任务运行
new AST(this).execute;  //assuming you've created an AsyncTask class called AST

以下是AsyncTasks的文档:http://developer.android.com/reference/android/os/AsyncTask.html

答案 3 :(得分:0)

问题是您正在UI线程上执行网络连接。对于性能和用户体验,Android不允许这样做。尝试在线程中包含getServerData()。

new Thread() {
    public void run() {
        getServerData();
    }
}.start();

答案 4 :(得分:0)

您不应该在Android应用的主要线程上进行网络活动。你需要为它分叉一个新线程。

请参阅this

答案 5 :(得分:0)

在所有Android版本3.0及更高版本中,如果您在UI线程(主线程)上进行任何网络调用,则会抛出该异常并且应用程序将立即崩溃。

您应该在AsyncTask上创建一个子类,并从那里调用您的getServerData方法。

Here是关于此主题的官方博客文章。

查看AsyncTask here