android.os.NetworkOnM<1>nThreadException 在4.0之后谷歌...

Android应用程序是由多个线程协作完成的,其中一个最常见的是UI线程。在应用程序中,我们经常需要通过网络获取数据,如果在UI线程内进行网络操作,会导致UI响应迟缓,甚至应用程序无响应的情况。因此,从Android 4.0版本开始,谷歌强制要求在UI线程中不再允许进行耗时操作。如果在UI线程中进行网络操作,就会抛出android.os.NetworkOnMainThreadException异常。

为了解决这个问题,需要通过以下几种方式:

方式一:使用AsyncTask异步任务

AsyncTask是Android提供的一种异步任务处理机制,非常常用。它可以在后台线程中执行任务,然后将执行结果返回给UI线程。在Android开发中,通过AsyncTask来实现网络访问非常方便,下面是一个使用AsyncTask的例子:

```

public class MainActivity extends Activity {

private TextView mTextView;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mTextView = (TextView) findViewById(R.id.text_view);

new DownloadTask().execute("http://www.baidu.com");

}

private class DownloadTask extends AsyncTask {

@Override

protected String doInBackground(String... params) {

String result = "";

try {

URL url = new URL(params[0]);

HttpURLConnection conn = (HttpURLConnection) url.openConnection();

conn.setRequestMethod("GET");

conn.connect();

if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {

InputStream is = conn.getInputStream();

BufferedReader br = new BufferedReader(new InputStreamReader(is));

String line;

while ((line = br.readLine()) != null) {

result += line;

}

is.close();

br.close();

}

conn.disconnect();

} catch (Exception e) {

e.printStackTrace();

}

return result;

}

@Override

protected void onPostExecute(String result) {

super.onPostExecute(result);

mTextView.setText(result);

}

}

}

```

在上面的例子中,我们在UI线程中创建了一个DownloadTask对象,并调用execute()方法启动异步任务。在异步任务中,我们使用HttpURLConnection进行网络连接,并在doInBackground()方法中得到了访问的结果,然后将结果传递给onPostExecute()方法,在该方法中更新UI界面。

注意,runOnUiThread()方法和Handler机制也可以完成异步任务,但这两种方法不如AsyncTask方便和实用。在处理渐进式图像和音频播放等情况下(如使用MediaPlayer),你可能需要使用Handler机制。

方式二: 新建线程

使用Thread和Handler机制也可以实现异步操作。在这种方式下,我们需要新建一个线程进行网络操作,然后使用Handler把结果传递回UI线程。以下是示例代码:

```

public class MainActivity extends Activity {

private TextView mTextView;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mTextView = (TextView) findViewById(R.id.text_view);

new Thread(new Runnable() {

@Override

public void run() {

final String result = download("http://www.baidu.com");

mTextView.post(new Runnable() {

@Override

public void run() {

mTextView.setText(result);

}

});

}

}).start();

}

private String download(String url) {

String result = "";

try {

URL urlObject = new URL(url);

HttpURLConnection conn = (HttpURLConnection) urlObject.openConnection();

conn.setRequestMethod("GET");

InputStream in = conn.getInputStream();

BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));

String line;

while ((line = reader.readLine()) != null) {

result += line;

}

} catch (Exception e) {

e.printStackTrace();

}

return result;

}

}

```

在上面的代码中,我们在UI线程中新建了一个线程,并在该线程中使用download()方法执行网络操作。注意,在download()方法中,我们需要使用HttpURLConnection进行网络连接,并把结果读取出来。最后把结果通过post()方法传递回UI线程。

方式三:通过使用HandlerThread线程

HandlerThread是Android的一个轻量级线程,它允许我们在后台线程中执行任务,并在UI线程中更新UI。以下是示例代码:

```

public class MainActivity extends Activity {

private TextView mTextView;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mTextView = (TextView) findViewById(R.id.text_view);

HandlerThread handlerThread = new HandlerThread("DownloadThread");

handlerThread.start();

Handler mHandler = new Handler(handlerThread.getLooper());

mHandler.post(new Runnable() {

@Override

public void run() {

final String result = download("http://www.baidu.com");

runOnUiThread(new Runnable() {

@Override

public void run() {

mTextView.setText(result);

}

});

}

});

}

private String download(String url) {

String result = "";

try {

URL urlObject = new URL(url);

HttpURLConnection conn = (HttpURLConnection) urlObject.openConnection();

conn.setRequestMethod("GET");

InputStream in = conn.getInputStream();

BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));

String line;

while ((line = reader.readLine()) != null) {

result += line;

}

} catch (Exception e) {

e.printStackTrace();

}

return result;

}

}

```

在上面的代码中,我们在UI线程中创建了一个HandlerThread对象,并启动了一个线程。在该线程中,我们使用Handler的post()方法执行网络操作,并把结果传递给UI线程。

总结

在Android 4.0及以后的版本上,谷歌禁止在UI线程中执行网络访问,否则会抛出NetworkOnMainThreadException异常。为了解决这个问题,我们可以使用AsyncTask、Thread和HandlerThread等方式,在后台线程中执行网络操作,并把结果传递给UI线程。无论使用哪种方式,都要遵循Android开发中异步操作的规则,避免卡死应用程序,提高用户体验。

壹涵网络我们是一家专注于网站建设、企业营销、网站关键词排名、AI内容生成、新媒体营销和短视频营销等业务的公司。我们拥有一支优秀的团队,专门致力于为客户提供优质的服务。

我们致力于为客户提供一站式的互联网营销服务,帮助客户在激烈的市场竞争中获得更大的优势和发展机会!

点赞(104) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿
发表
评论
返回
顶部