android.os.networkonmainthredexception,如何修复android.os.NetworkOnMainThreadException?

接受的答案有一些重要的缺点。除非你真的知道自己在做什么,否则不建议使用AsyncTask进行网络连接。一些不利方面包括:

作为非静态内部类创建的AsyncTask具有对封闭的Activity对象,其上下文以及该活动创建的整个View层次结构的隐式引用。此引用可防止在AsyncTask的后台工作完成之前对Activity进行垃圾回收。如果用户的连接速度很慢,和/或下载量很大,则这些短期内存泄漏可能会成为问题 - 例如,如果方向发生多次更改(并且您没有取消执行的任务),或者用户导航远离活动。

AsyncTask具有不同的执行特性,具体取决于它执行的平台:API级别4之前AsyncTasks在单个后台线程上串行执行; 从API级别4到API级别10,AsyncTasks在最多128个线程的池上执行; 从API级别11开始,AsyncTask在单个后台线程上串行执行(除非您使用重载executeOnExecutor方法并提供备用执行程序)。当在Gingerbread上同时执行时,在ICS上串行运行时运行正常的代码可能会中断,例如,如果您有无意的执行顺序依赖项。

如果您想避免短期内存泄漏,在所有平台上都有明确定义的执行特性,并且有基础来构建非常强大的网络处理,您可能需要考虑:

使用一个能为你做得很好的库 - 在这个问题中对网络库进行了很好的比较,或者

使用a Service或者IntentService替代,也许使用a PendingIntent来通过Activity的onActivityResult方法返回结果。

IntentService方法

下行方面:

更多的代码和复杂性AsyncTask,虽然没有您想象的那么多

将队列请求排队并在单个后台线程上运行它们。您可以通过替换IntentService等效Service实现来轻松控制此操作,也许就像这样。

嗯,实际上我现在想不出任何其他人

向上方面:

避免短期内存泄漏问题

如果您的活动在网络操作正在进行时重新启动,它仍然可以通过其onActivityResult方法接收下载结果

比AsyncTask更好的平台来构建和重用强大的网络代码。示例:如果您需要执行重要上传,则可以从中AsyncTask进行Activity,但如果用户上下文切换出应用程序以进行电话呼叫,则系统可能会在上载完成之前终止应用程序。它不太可能杀死具有活动的应用程序Service。

如果您使用自己的并发版本IntentService(如上面链接的那个),您可以通过控制并发级别来控制并发级别Executor。

实施摘要

您可以IntentService非常轻松地实现在单个后台线程上执行下载。

第1步:创建一个IntentService以执行下载。您可以通过Intentextra 来告诉它要下载什么,并将其传递PendingIntent给用于将结果返回到Activity:

import android.app.IntentService;

import android.app.PendingIntent;

import android.content.Intent;

import android.util.Log;

import java.io.InputStream;

import java.net.MalformedURLException;

import java.net.URL;

public class DownloadIntentService extends IntentService {

private static final String TAG = DownloadIntentService.class.getSimpleName();

public static final String PENDING_RESULT_EXTRA = "pending_result";

public static final String URL_EXTRA = "url";

public static final String RSS_RESULT_EXTRA = "url";

public static final int RESULT_CODE = 0;

public static final int INVALID_URL_CODE = 1;

public static final int ERROR_CODE = 2;

private IllustrativeRSSParser parser;

public DownloadIntentService() {

super(TAG);

// make one and re-use, in the case where more than one intent is queued

parser = new IllustrativeRSSParser();

}

@Override

protected void onHandleIntent(Intent intent) {

PendingIntent reply = intent.getParcelableExtra(PENDING_RESULT_EXTRA);

InputStream in = null;

try {

try {

URL url = new URL(intent.getStringExtra(URL_EXTRA));

IllustrativeRSS rss = parser.parse(in = url.openStream());

Intent result = new Intent();

result.putExtra(RSS_RESULT_EXTRA, rss);

reply.send(this, RESULT_CODE, result);

} catch (MalformedURLException exc) {

reply.send(INVALID_URL_CODE);

} catch (Exception exc) {

// could do better by treating the different sax/xml exceptions individually

reply.send(ERROR_CODE);

}

} catch (PendingIntent.CanceledException exc) {

Log.i(TAG, "reply cancelled", exc);

}

}

}

第2步:在清单中注册服务:

android:name=".DownloadIntentService"

android:exported="false"/>

步骤3:从Activity调用服务,传递PendingResult对象,Service将使用该对象返回结果:

PendingIntent pendingResult = createPendingResult(

RSS_DOWNLOAD_REQUEST_CODE, new Intent(), 0);

Intent intent = new Intent(getApplicationContext(), DownloadIntentService.class);

intent.putExtra(DownloadIntentService.URL_EXTRA, URL);

intent.putExtra(DownloadIntentService.PENDING_RESULT_EXTRA, pendingResult);

startService(intent);

第4步:处理onActivityResult中的结果:

@Override

protected void onActivityResult(int requestCode, int resultCode, Intent data) {

if (requestCode == RSS_DOWNLOAD_REQUEST_CODE) {

switch (resultCode) {

case DownloadIntentService.INVALID_URL_CODE:

handleInvalidURL();

break;

case DownloadIntentService.ERROR_CODE:

handleError(data);

break;

case DownloadIntentService.RESULT_CODE:

handleRSS(data);

break;

}

handleRSS(data);

}

super.onActivityResult(requestCode, resultCode, data);

}

包含一个完整的工作Android的工作室/ gradle这个项目一个项目的GitHub可以在这里。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值