Android – android.os.NetworkOnMainThreadException
我有这个例外,我正在阅读一个线程,这似乎令人困惑:
如何解决android.os.NetworkOnMainThreadException?
我已经将这一行添加到我的清单中:
<uses-permission android:name="android.permission.INTERNET" />
在这个讨论中,他们讨论了应用程序的主要执行线程不能够进行联网。 我想知道的是如何重构我的代码,以便与Android良好实践保持一致。
这是我的Activity类:
package com.problemio; import java.io.InputStream; 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 android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; public class LoginActivity extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.login); // Show form for login_email final EditText loginEmail = (EditText) findViewById(R.id.login_email); String name = loginEmail.getText().toString(); // Show field for password final EditText password = (EditText) findViewById(R.id.password); String text = password.getText().toString(); // Show button for submit Button submit = (Button)findViewById(R.id.submit); // Show options for create-profile and forgot-password submit.setOnClickListener(new Button.OnClickListener() { public void onClick(View v) { String email = loginEmail.getText().toString(); String pass = password.getText().toString(); sendFeedback(pass, email); } }); } public void sendFeedback(String pass , String email) { Log.d( "1" , pass ); Log.d( "1" , email ); // Go to db and check if these r legit // How do I do that? :) ArrayList<NameValuePair> postParameters = new ArrayList<NameValuePair>(); postParameters.add(new BasicNameValuePair("username", email )); postParameters.add(new BasicNameValuePair("password", pass )); String responseString = null; try { HttpClient httpclient = new DefaultHttpClient(); HttpPost httppost = new HttpPost("myUrl"); // no idea what this does :) httppost.setEntity(new UrlEncodedFormEntity(postParameters)); // This is the line that send the request HttpResponse response = httpclient.execute(httppost); HttpEntity entity = response.getEntity(); InputStream is = entity.getContent(); } catch (Exception e) { Log.e("log_tag", "Error in http connection "+e.toString()); } } }
我在这里做错了什么,我该如何解决? :) 谢谢!!
NetworkOnMainThreadException:应用程序尝试在其主线程上执行联网操作时引发的exception。
你应该在asynctask上调用sendfeedback方法,然后只有上面的代码才能工作。 由于Web服务器需要大量的时间来响应主线程变得无法响应。 为了避免它,你应该在另一个线程上调用它。 因此,asynctask更好。
这里是说明如何使用asynctask的链接
当您的应用程序尝试在主线程中进行联网操作时,会引发NetworkOnMainThreadException 。
为了解决这个问题,你可以在你的Activity中使用一个私有的内部类来扩展android.os.AsyncTask<Params, Progress, Result>
,它将执行服务器调用的东西。
东西,
private class SendfeedbackJob extends AsyncTask<String, Void, String> { @Override protected String doInBackground(String[] params) { // do above Server call here return "some message"; } @Override protected void onPostExecute(String message) { //process message } }
然后如下所示从submit.setOnClickListener
调用上面的类,
SendfeedbackJob job = new SendfeedbackJob(); job.execute(pass, email);
参考
AsyncTask文档
AsyncTask的Android例子
if (android.os.Build.VERSION.SDK_INT > 9) { StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy); }
try { HttpClient httpclient = new DefaultHttpClient(); HttpPost httppost = new HttpPost("myUrl"); // no idea what this does :) httppost.setEntity(new UrlEncodedFormEntity(postParameters)); // This is the line that send the request HttpResponse response = httpclient.execute(httppost); HttpEntity entity = response.getEntity(); InputStream is = entity.getContent(); } catch (Exception e) { Log.e("log_tag", "Error in http connection "+e.toString()); }
这是你的问题。 由于api 11,这个例外会告诉你,你正在ui线程上运行很长的任务(你class上的http通信),并且根据新的StrictGuard策略,这是不可能的。 所以你有两个不同的select
- 使用线程或aynctask来执行你的长期任务(更好的方法)
你在主线程上进行了违反android规则的networking调用,所以你必须在asynctask或handler等单独的线程上进行networking调用。
你可以像下面那样创buildAsync类
class Retrievedata extends AsyncTask<String, Void, String> { @Override protected String doInBackground(String... params) { try{ //Your code } return null; } }
你可以把你所有的代码放在doInBackground方法里面
看看这个链接: https : //developer.android.com/reference/android/os/NetworkOnMainThreadException.html
应用程序尝试在其主线程上执行联网操作时引发的exception。 针对较早的SDK版本的应用程序被允许在其主要事件循环线程上进行联网,但是非常不鼓励。
如果你设置minSdkVersion <11,那么你的应用程序将工作,你可以在主线程中运行networking操作。
主线程是UI线程,您不能在主线程中执行可能会阻止用户交互的操作。为了避免这种情况,您可以创build一个简单的处理程序并更新主线程。
Runnable runnable; Handler newHandler; newHandler = new Handler(); runnable = new Runnable() { @Override public void run() { try { //update UI } catch (Exception e) { e.printStackTrace(); } } }; runnable.run();
停止线程使用
newHandler.removeCallbacks(可运行);
欲了解更多信息检查了这一点。 https://android-developers.googleblog.com/2009/05/painless-threading.html
经过长时间的研究(历时半天),我find了一个解决我的问题的方法,类似于这里指出的问题。 我的Android Studio 2.3.3显示的exception是这样的:
android studio android.os.networkonmainthreadexception
问题是基于在MainActivity中设置UIvariables的不可能性。 所以我看到下面的video,我解决了我的问题。 我希望对别人也有用:
如何避免android os的NetworkOnMainThreadException
- 如何滚动到RecyclerView的底部? scrollToPosition不起作用
- 任何协作工具/网站本地化的Android应用程序?
- 调用ListView.addHeaderView()时发生ClassCastException?
- OnLocationChangedcallback永远不会被调用
- Android基本authentication的OkHttp
- 在API 17之前从RelativeLayout中移除规则
- Android工作室添加外部项目build.gradle
- 如何在偏好摘要中显示Android偏好设置的当前值?
- Android / Eclipse:我如何在res / drawable文件夹中添加图片?