How to fix 'android.os.NetworkOnMainThreadExce

2020-01-22 09:35发布

I got an error while running my Android project for RssReader.

Code:

URL url = new URL(urlToRssFeed);
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
XMLReader xmlreader = parser.getXMLReader();
RssHandler theRSSHandler = new RssHandler();
xmlreader.setContentHandler(theRSSHandler);
InputSource is = new InputSource(url.openStream());
xmlreader.parse(is);
return theRSSHandler.getFeed();

And it shows the below error:

android.os.NetworkOnMainThreadException

How can I fix this issue?

30条回答
我命由我不由天
2楼-- · 2020-01-22 10:24

Put your code inside:

new Thread(new Runnable(){
    @Override
    public void run() {
        try {
            // Your implementation
        }
        catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}).start();

Or:

class DemoTask extends AsyncTask<Void, Void, Void> {

    protected Void doInBackground(Void... arg0) {
        //Your implementation
    }

    protected void onPostExecute(Void result) {
        // TODO: do something with the feed
    }
}
查看更多
仙女界的扛把子
3楼-- · 2020-01-22 10:25

Using Android Annotations is an option. It will allow you to simply run any method in a background thread:

// normal method
private void normal() {
    doSomething(); // do something in background
}

@Background
protected void doSomething() 
    // run your networking code here
}

Note, that although it provides benefits of simplicity and readability, it has its disadvantages.

查看更多
我命由我不由天
4楼-- · 2020-01-22 10:25

For me it was this:

<uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="10" />

The device I was testing my app on was 4.1.2 which is SDK Version 16!

Make the sure the target version is the same as your Android Target Library. If you are unsure what your target library is, right click your Project -> Build Path -> Android, and it should be the one that is ticked.

Also, as others have mentioned, include the correct permissions to access the Internet:

<uses-permission android:name="android.permission.INTERNET"/>
查看更多
Summer. ? 凉城
5楼-- · 2020-01-22 10:27

You are able to move a part of your code into another thread to offload the main thread and avoid getting ANR, NetworkOnMainThreadException, IllegalStateException(e.g. Cannot access database on the main thread since it may potentially lock the UI for a long period of time).

There are some approaches that you should choose depends on the situation

Java Thread or Android HandlerThread

Java threads are one-time use only and die after executing its run method.

HandlerThread is a handy class for starting a new thread that has a looper.

AsyncTask

AsyncTask is designed to be a helper class around Thread and Handler and does not constitute a generic threading framework. AsyncTasks should ideally be used for short operations (a few seconds at the most.) If you need to keep threads running for long periods of time, it is highly recommended you use the various APIs provided by the java.util.concurrent package such as Executor, ThreadPoolExecutor and FutureTask.

Thread pool implementation ThreadPoolExecutor, ScheduledThreadPoolExecutor...

ThreadPoolExecutor class that implements ExecutorService which gives fine control on the thread pool (Eg, core pool size, max pool size, keep alive time, etc.)

ScheduledThreadPoolExecutor - a class that extends ThreadPoolExecutor. It can schedule tasks after a given delay or periodically.

FutureTask

FutureTask performs asynchronous processing, however, if the result is not ready yet or processing has not complete, calling get() will be block the thread

AsyncTaskLoaders

AsyncTaskLoaders as they solve a lot of problems that are inherent to AsyncTask

IntentService

This is the defacto choice for long running processing on Android, a good example would be to upload or download large files. The upload and download may continue even if the user exits the app and you certainly do not want to block the user from being able to use the app while these tasks are going on.

JobScheduler

Effectively, you have to create a Service and create a job using JobInfo.Builder that specifies your criteria for when to run the service.

RxJava

Library for composing asynchronous and event-based programs by using observable sequences.

Coroutines (Kotlin)

The main gist of it is, it makes asynchronous code looks so much like synchronous

Read more here, here, here, here

查看更多
Melony?
6楼-- · 2020-01-22 10:28

Just to spell out something explicitly:

The main thread is basically the UI thread.

So saying that you cannot do networking operations in the main thread means you cannot do networking operations in the UI thread, which means you cannot do networking operations in a *runOnUiThread(new Runnable() { ... }* block inside some other thread, either.

(I just had a long head-scratching moment trying to figure out why I was getting that error somewhere other than my main thread. This was why; this thread helped; and hopefully this comment will help someone else.)

查看更多
Melony?
7楼-- · 2020-01-22 10:29

This exception occurs due to any heavy task performed on the main thread if that performing task takes too much time.

To avoid this, we can handle it using threads or executers

Executors.newSingleThreadExecutor().submit(new Runnable() {
    @Override
    public void run() {
        // You can perform your task here.
    }
});
查看更多
登录 后发表回答