49

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

如何修复 android.os.NetworkOnMainThreadException?

我已经将此行添加到我的清单中:

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

在那次讨论中,他们谈到了应用程序的主执行线程无法联网。我想知道的是如何重组我的代码,使其符合 Android 的良好实践。

这是我的活动课程:

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

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

4

10 回答 10

58

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

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

这是说明如何使用 asynctask的链接

于 2012-02-23T15:15:31.770 回答
35

当您的应用尝试在主线程中进行网络操作时,会引发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 Android 示例

于 2015-01-05T21:53:21.620 回答
12
if (android.os.Build.VERSION.SDK_INT > 9) {
    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
    StrictMode.setThreadPolicy(policy);
}
于 2013-06-12T11:02:22.933 回答
8
 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 来执行你的长期任务(更好的方法)
于 2012-02-23T13:08:56.950 回答
3

您可以按如下方式创建 Async 类

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

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

于 2014-05-08T04:33:50.043 回答
3

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

于 2012-02-23T13:09:40.203 回答
0

如此处所示,AsyncTask已弃用,Google 建议您使用java.util.concurrent包或Kotlin 协程

您可以使用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()

}
于 2021-09-16T13:58:54.220 回答
0

在这种情况下使用线程,

Thread thread = new Thread(new Runnable() {

    @Override
    public void run() {
        try  {
            //Code here
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
});

thread.start(); 

于 2021-08-17T10:05:26.043 回答
0

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

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

如果您设置 minSdkVersion <11,那么您的应用程序将工作并且您可以在主线程中运行网络操作。

于 2017-06-03T09:25:12.297 回答
0

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

android studio android.os.networkonmainthreadexception

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

如何避免android os NetworkOnMainThreadException

于 2017-09-06T19:53:47.673 回答