Android 应用因 NetworkOnMainThreadException 而崩溃
Android app crashes due to NetworkOnMainThreadException
我想开发一个应用程序,允许我从 android 应用程序的形式将数据作为文本文件上传到服务器
这是主要活动 class
package com.example.incrediblemachine.sendtest;
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.Toast;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
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 java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends Activity {
EditText msgTextField;
Button sendButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//make message text field object
msgTextField = (EditText) findViewById(R.id.msgTextField);
//make button object
sendButton = (Button) findViewById(R.id.sendButton);
}
public void send(View v)
{
//get message from message box
String msg = msgTextField.getText().toString();
//check whether the msg empty or not
if(msg.length()>0) {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://ramsproject.16mb.com/sendorder.php");
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("id", "01"));
nameValuePairs.add(new BasicNameValuePair("message", msg));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
httpclient.execute(httppost);
msgTextField.setText(""); //reset the message text field
Toast.makeText(getBaseContext(),"Sent",Toast.LENGTH_SHORT).show();
}catch (IllegalStateException e)
{
e.printStackTrace();
}
catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} else {
//display message if text field is empty
Toast.makeText(getBaseContext(),"All fields are required",Toast.LENGTH_SHORT).show();
}
}
}
它在第 53 行出现异常
httpclient.execute(httppost);
异常显示 android.app.NetworkOnMainThreadException
我该如何解决这个问题
只需使用一个线程。
Thread thread = new Thread(new Runnable(){
@Override
public void run() {
try {
//Your code goes here
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread.start();
在此线程中调用 httpClient。
您不能在 MainThread 中进行网络调用。您应该为网络操作使用异步任务。您可以从下面的 link 中找到有关它的更多信息:
https://developer.android.com/reference/android/os/AsyncTask.html
我还建议您使用网络库来处理您的网络操作。您可以从下面的 link 中为您的网络操作找到一个好的库:
当应用程序试图在其主线程上执行网络操作时抛出的异常。
允许以 Honeycomb SDK 或更高版本为目标的应用程序在其主事件循环线程上进行联网,以避免在与网络相关的无响应情况下出现迟缓。你可以参考Documentation.
要解决此问题,您可以选择以下选项:
1.Using 异步任务
2.线程
3.处理程序
我想在这里为您提供一个解决方案。为此,我想在您了解解决方案之前指出几点。
在 UI 线程或主线程,进一步阅读以了解这一点。
每个 Android 应用程序 运行 在其自己的进程中并具有唯一的用户 ID。每当安装 android 应用程序时,它都会获得一个唯一的用户 ID。每当应用程序 运行 时,它都会获得一个单独的内存 space 和程序执行路径。这个进程由它自己的称为堆的内存组成。进程就像一个单独的环境给你的应用程序运行代码或进程代码。
另一方面,线程是子进程或轻量级进程。它在进程内部产生。每当创建一个线程时,它都会获得一部分内存(堆栈)。一个进程可以产生许多线程。
一个线程不能访问另一个线程的内存(栈),它是特定线程私有的。但是他们可以访问进程内存(堆内存)。将堆内存视为全局内存。
每当为您的应用程序创建一个进程时,都会创建一个线程,这是强制性的。该线程称为主线程。在 android 中它也可能被称为 UI 线程。因为此线程处理您看到的所有 UI 组件(如 activity、片段和服务(即使服务在后台 运行,它在 UI线程)等)。
Android 框架的创建方式是他们希望处理主线程上的所有 UI 操作,使其具有高优先级来处理 UI组件。因为 UI 是显示给用户的,如果应用程序在未处理 UI.
的情况下被冻结,用户将不会喜欢该应用程序
这就是您得到 "NetworkOnMainThread" 异常的原因。因为 Android 限制 运行ning 长 运行ning 操作,如网络访问、文件访问、数据库访问以及 运行 在 UI 线程上的那些处理。因为限制 UI 响应需要花费很多时间,因为它没有给 UI 组件处理机会。
我希望你明白为什么你现在会得到这样的异常。长 运行ning 操作不应限制 UI 线程操作。所以它应该从 UI 线程移动到另一个新线程(移动你创建 HttpClient 的代码,直到你收到它的响应)。 Android 还为此提供了另一种选择。您可以创建一个 AsyncTask,它会为您处理线程创建过程。您可以只编写代码并将结果传递给 UI 线程。了解更多。
注意:所有线程都访问进程内存。但是一个进程不能访问另一个进程的内存,除非它有相同的 USER ID。意味着除非它来自您的应用程序之一。这可以使用 AIDL 接口完成。
我希望这个解决方案能帮助您理解您遇到的异常并解决它们。
我想开发一个应用程序,允许我从 android 应用程序的形式将数据作为文本文件上传到服务器 这是主要活动 class
package com.example.incrediblemachine.sendtest;
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.Toast;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
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 java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends Activity {
EditText msgTextField;
Button sendButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//make message text field object
msgTextField = (EditText) findViewById(R.id.msgTextField);
//make button object
sendButton = (Button) findViewById(R.id.sendButton);
}
public void send(View v)
{
//get message from message box
String msg = msgTextField.getText().toString();
//check whether the msg empty or not
if(msg.length()>0) {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("http://ramsproject.16mb.com/sendorder.php");
try {
List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(2);
nameValuePairs.add(new BasicNameValuePair("id", "01"));
nameValuePairs.add(new BasicNameValuePair("message", msg));
httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
httpclient.execute(httppost);
msgTextField.setText(""); //reset the message text field
Toast.makeText(getBaseContext(),"Sent",Toast.LENGTH_SHORT).show();
}catch (IllegalStateException e)
{
e.printStackTrace();
}
catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} else {
//display message if text field is empty
Toast.makeText(getBaseContext(),"All fields are required",Toast.LENGTH_SHORT).show();
}
}
}
它在第 53 行出现异常 httpclient.execute(httppost);
异常显示 android.app.NetworkOnMainThreadException 我该如何解决这个问题
只需使用一个线程。
Thread thread = new Thread(new Runnable(){
@Override
public void run() {
try {
//Your code goes here
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread.start();
在此线程中调用 httpClient。
您不能在 MainThread 中进行网络调用。您应该为网络操作使用异步任务。您可以从下面的 link 中找到有关它的更多信息:
https://developer.android.com/reference/android/os/AsyncTask.html
我还建议您使用网络库来处理您的网络操作。您可以从下面的 link 中为您的网络操作找到一个好的库:
当应用程序试图在其主线程上执行网络操作时抛出的异常。 允许以 Honeycomb SDK 或更高版本为目标的应用程序在其主事件循环线程上进行联网,以避免在与网络相关的无响应情况下出现迟缓。你可以参考Documentation.
要解决此问题,您可以选择以下选项: 1.Using 异步任务 2.线程 3.处理程序
我想在这里为您提供一个解决方案。为此,我想在您了解解决方案之前指出几点。
-
在 UI 线程或主线程,进一步阅读以了解这一点。
每个 Android 应用程序 运行 在其自己的进程中并具有唯一的用户 ID。每当安装 android 应用程序时,它都会获得一个唯一的用户 ID。每当应用程序 运行 时,它都会获得一个单独的内存 space 和程序执行路径。这个进程由它自己的称为堆的内存组成。进程就像一个单独的环境给你的应用程序运行代码或进程代码。
另一方面,线程是子进程或轻量级进程。它在进程内部产生。每当创建一个线程时,它都会获得一部分内存(堆栈)。一个进程可以产生许多线程。
一个线程不能访问另一个线程的内存(栈),它是特定线程私有的。但是他们可以访问进程内存(堆内存)。将堆内存视为全局内存。
每当为您的应用程序创建一个进程时,都会创建一个线程,这是强制性的。该线程称为主线程。在 android 中它也可能被称为 UI 线程。因为此线程处理您看到的所有 UI 组件(如 activity、片段和服务(即使服务在后台 运行,它在 UI线程)等)。
Android 框架的创建方式是他们希望处理主线程上的所有 UI 操作,使其具有高优先级来处理 UI组件。因为 UI 是显示给用户的,如果应用程序在未处理 UI.
的情况下被冻结,用户将不会喜欢该应用程序
这就是您得到 "NetworkOnMainThread" 异常的原因。因为 Android 限制 运行ning 长 运行ning 操作,如网络访问、文件访问、数据库访问以及 运行 在 UI 线程上的那些处理。因为限制 UI 响应需要花费很多时间,因为它没有给 UI 组件处理机会。
我希望你明白为什么你现在会得到这样的异常。长 运行ning 操作不应限制 UI 线程操作。所以它应该从 UI 线程移动到另一个新线程(移动你创建 HttpClient 的代码,直到你收到它的响应)。 Android 还为此提供了另一种选择。您可以创建一个 AsyncTask,它会为您处理线程创建过程。您可以只编写代码并将结果传递给 UI 线程。了解更多。
注意:所有线程都访问进程内存。但是一个进程不能访问另一个进程的内存,除非它有相同的 USER ID。意味着除非它来自您的应用程序之一。这可以使用 AIDL 接口完成。
我希望这个解决方案能帮助您理解您遇到的异常并解决它们。