【问题标题】:Android - android.os.NetworkOnMainThreadExceptionAndroid - android.os.NetworkOnMainThreadException
【发布时间】:2012-03-13 21:24:55
【问题描述】:

我有这个例外,我正在阅读一个关于此的线程,它似乎令人困惑:

How to fix 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());
        }        
    }          
}

我在这里做错了什么,我该如何解决? :) 谢谢!!

【问题讨论】:

标签: android networkonmainthread


【解决方案1】:

NetworkOnMainThreadException:当应用程序尝试在其主线程上执行网络操作时引发的异常。

您应该在 asynctask 上调用 sendfeedback 方法,然后只有上面的代码才能工作。由于网络服务器需要大量时间来响应主线程变得无响应。为避免它,您应该在另一个线程上调用它。因此 asynctask 更好。

这里是link,它说明了如何使用异步任务

【讨论】:

  • AsyncTask 现已弃用,更好的选择是使用java.util.concurrent.Executors 在另一个线程中执行网络任务。
【解决方案2】:

NetworkOnMainThreadException 在您的应用尝试在主线程中进行网络操作时抛出。

要解决此问题,您可以在 Activity 中使用扩展 android.os.AsyncTask&lt;Params, Progress, Result&gt; 的私有内部类,该类将执行服务器调用。

某事,

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 doc

AsyncTask Android example

【讨论】:

  • 来吧伙计,太美了:)
【解决方案3】:
if (android.os.Build.VERSION.SDK_INT > 9) {
    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
    StrictMode.setThreadPolicy(policy);
}

【讨论】:

  • 不是真的,当您只需要一个小测试并为此创建一个新的小型 android 项目时.. :)
  • 这是个好主意,如果您只是测试应用程序的数据操作,并且暂时不想打扰线程。
  • 严格不推荐,但如果您正在测试某些功能并且需要更快地完成它,您可以使用它。强烈建议您不要在生产环境中使用它。我们不想要设计糟糕的应用,不是吗?
  • 更多讨论(45 cmets!)见这里:stackoverflow.com/a/9289190/253938
【解决方案4】:
 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 线程(您的类中的 http 通信)上运行长任务,并且根据新的 StrictGuard 策略,这是不可能的。所以你有两种不同的选择

  1. 使用线程或 aynctask 来执行您的长期任务(更好的方式)

【讨论】:

  • 关于更改StrictMode.setThreadPolicy你可以阅读这个:android-er.blogspot.com/2012/04/…
  • ^ 这对我们有帮助。非常感谢:)
  • 这段代码什么都不做?这怎么可能是答案?
  • 我提供了对该问题的解释。 sn-p 是为了指出错误,而不是解决 op 的问题。 @Cicorias
  • 在进行编辑之前,我现在无法投票。我现在同意。
【解决方案5】:

您在主线程上进行了网络调用,这违反了 android 规则,因此您必须在单独的线程上进行网络调用,例如 asynctask 或处理程序等。

【讨论】:

    【解决方案6】:

    你可以像下面这样创建异步类

    class Retrievedata extends AsyncTask<String, Void, String> {
    @Override
        protected String doInBackground(String... params) {
             try{
                    //Your code 
                    }
            return null;
        }
    }
    

    您可以将所有代码放入 doInBackground 方法中

    【讨论】:

    【解决方案7】:

    看看这个链接:https://developer.android.com/reference/android/os/NetworkOnMainThreadException.html

    当应用程序尝试在其主线程上执行网络操作时引发的异常。 允许针对早期 SDK 版本的应用程序在其主事件循环线程上进行联网,但非常不鼓励这样做。

    如果您设置 minSdkVersion

    【讨论】:

      【解决方案8】:

      经过长时间的研究(持续半天),我找到了一个与此处指出的问题类似的问题的解决方案。我的 Android Studio 2.3.3 显示的异常是这样的:

      android studio android.os.networkonmainthreadexception

      问题是因为无法在 MainActivity 中设置 UI 变量。所以我看到了下面的视频,我解决了我的问题。我希望它对其他人也有用:

      How to avoid android os NetworkOnMainThreadException

      【讨论】:

        【解决方案9】:

        在这种情况下使用线程,

        Thread thread = new Thread(new Runnable() {
        
            @Override
            public void run() {
                try  {
                    //Code here
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        
        thread.start(); 

        【讨论】:

          【解决方案10】:

          here 所示,AsyncTask 已弃用,Google 建议您使用 java.util.concurrent 包或 Kotlin coroutines

          您可以使用java.util.concurrent.Executors 非常轻松地在另一个线程中执行您的网络任务。

          只需将这两个变量添加到您的 LoginActivity 类中:

          val executor = Executors.newSingleThreadExecutor()
          

          然后用executor.execute{} 块包围您的网络呼叫:

          executor.execute {
              /**
               * Executes network task in background. You cannot
               * access view elements here.
               */
              
              HttpResponse response = httpclient.execute(httppost);
              
              HttpEntity entity = response.getEntity();            
          
              InputStream is = entity.getContent()
          
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2013-10-16
            • 2013-05-02
            • 2013-04-24
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多