【问题标题】:NetworkOnMainThreadException [duplicate]NetworkOnMainThreadException [重复]
【发布时间】:2011-07-06 06:10:57
【问题描述】:

我刚刚在官方文档中发现了 NetworkOnMainThreadException

并且想知道模拟器是否正在抛出这个。我已经对我的应用程序进行了相当多的测试,据我所知,所有网络都在主线程之外(使用 Roboguice RoboAsyncTask),但你永远不知道是否有人没有逃脱。

我也在使用 StrictMode,但什么也没看到。

  1. 我的代码是干净的还是没有在模拟器上抛出?

  2. 我们应该如何为生产中发生的这种情况做准备?

  3. 宽限期之类的呢? 或者现在已经过去了;-) ??

【问题讨论】:

  • 这是在 Android 3.0 中引入的。正如文档所述,当我在 UI 线程上进行网络操作时,我得到了它。我移动并在单独的线程上运行该操作,但它消失了。
  • 您也可以在模拟器中获得它,还是仅通过设备获得?没有启用 StrictMode?​​span>
  • 我在模拟器上得到了它,没有在 StrictMode 下运行。
  • 如果你想确定它会导致错误消息,故意造成这种情况应该不难。
  • @Samuh 我可以问一下当您遇到 NetworkOnMainThreadException 时您使用的是哪个版本的 android 模拟器?因为我根本无法在模拟器上重现这个错误。谢谢!

标签: android networking asynchronous android-asynctask networkonmainthread


【解决方案1】:

使用honeycomb,您无法在其主线程上执行网络操作,如文档所述。出于这个原因,您必须使用处理程序或异步任务。没有其他方法可以做到这一点。

在这里您可以找到 2 个用土耳其语编写的关于网络操作的示例。也许他们有帮助。

【讨论】:

  • 使用Handler 不一定能解决问题。 Handler 的默认行为也在主 (UI) 线程上执行。
【解决方案2】:

我已经对此进行了测试,实际上它也发生在模拟器上。如果您打算将应用程序安装到 3.0 平板电脑及更高版本上,最好确保至少在模拟器上对其进行测试。

【讨论】:

  • 文档这样说:“这仅适用于针对 Honeycomb SDK 或更高版本的应用程序。针对早期 SDK 版本的应用程序允许在其主事件循环线程上进行联网,但非常不鼓励这样做。请参阅响应性设计文档。”
  • Read my blog post on the NetworkOnMainThreadException for more information. 它解释了为什么会在 Android 3.0 及更高版本上发生这种情况。
【解决方案3】:

NetworkOnMainThreadException 在 main 方法内部执行一些网络操作时发生;我的意思是Oncreate()。您可以使用AsyncTask 来解决此问题。或者你可以使用

StrictMode.ThreadPolicy mypolicy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);

onCreate() 方法内。

【讨论】:

  • 这是错误的。在 主线程 上执行网络 I/O 时会引发异常。这可能发生在任何方法中,而不仅仅是onCreate()
【解决方案4】:

如果您在 3.0 上运行,我无能为力;因为它默认开启了严格模式;但它的上面tat,那么这可能会有所帮助

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);

在您的 HTTP 连接创建之前包含此内容;然后就可以了

【讨论】:

  • 老答案,但请放心:这是错误的做法!永远不要在 UI 线程上使用任何网络内容。你造成的每一毫秒延迟都会有一只小猫死亡......
【解决方案5】:

从Honeycomb SDK(3)开始,Google将不再允许在Main Thread类中直接进行网络请求(HTTP、Socket)等相关操作,实际上不应该在UI线程中直接进行网络操作,阻塞UI,用户体验很差!就算不禁止谷歌,一般情况下,我们也不会这样做~! 所以,也就是在Honeycomb SDK(3)版本中,你也可以在Main Thread中继续这样做,超过3就不行了。

1.使用Handler

与网络相关的比较耗时的操作放在子线程中,然后使用Handler消息机制与主线程通信

public static final String TAG = "NetWorkException";

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.setContentView(R.layout.activity_net_work_exception);
    // Opens a child thread, performs network operations, waits for a return result, and uses handler to notify UI
    new Thread(networkTask).start();
}

Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        // get data from msg and notify UI
        Bundle data = msg.getData();
        String val = data.getString("data");
        Log.i(TAG, "the result-->" + val);
    }
};

/**
 * net work task
 */
Runnable networkTask = new Runnable() {

    @Override
    public void run() {
        // do here, the HTTP request. network requests related operations
        Message msg = new Message();
        Bundle data = new Bundle();
        data.putString("data", "request");
        msg.setData(data);
        handler.sendMessage(msg);
    }
};

2.使用AsyncTask

public static final String TAG = "NetWorkException";
private ImageView mImageView;

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.setContentView(R.layout.activity_net_work_exception);
    mImageView = findViewById(R.id.image_view);
    new DownImage(mImageView).execute();
}


class DownImage extends AsyncTask<String, Integer, Bitmap> {

    private ImageView imageView;

    public DownImage(ImageView imageView) {
        this.imageView = imageView;
    }

    @Override
    protected Bitmap doInBackground(String... params) {
        String url = params[0];
        Bitmap bitmap = null;
        try {
            //load image from internet , http request here
            InputStream is = new URL(url).openStream();
            bitmap = BitmapFactory.decodeStream(is);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bitmap;
    }

    @Override
    protected void onPostExecute(Bitmap result) {
        // nodify UI here
        imageView.setImageBitmap(result);
    }
}

3.使用StrictMode

if (android.os.Build.VERSION.SDK_INT > 9) {
    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
    StrictMode.setThreadPolicy(policy);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-08
    • 2014-06-27
    • 1970-01-01
    • 2019-03-24
    • 1970-01-01
    相关资源
    最近更新 更多