I believe many Android developers have encountered android.os.NetworkOnMainThreadException this anomaly, meaning that the main thread for network operation exception. This is a simple question, but there are a bunch of different answers on the web, and it's a good time to take a moment to do a more complete description.
Strict mode
In earlier versions of Android (prior to 2.3), Google did not provide a very strict program writing requirement, so at that time we could perform local IO operations, network operations, and other non-canonical behaviors in the main thread. Later in 2.3 Gingerbread (gingerbread) began to provide a developer tool, which is Strictmode strict mode.
Strict mode helps developers find disk operations and network operations in the main thread, and developers can improve programs to better respond to user actions based on strict mode output information, with less ANR (program not responding) issues.
Android.os.NetworkOnMainThreadException This exception is introduced from Android 3.0 (API 11) and occurs as the main thread for network operation.
Code Open Strictmode
if (Build.VERSION.SDK_INT >= version_codes. Gingerbread) { new StrictMode.ThreadPolicy.Builder (); Threadpolicybuilder.detectdiskreads (). Detectdiskwrites (). Detectnetwork (). Penaltylog (); Strictmode.setthreadpolicy (Threadpolicybuilder.build ()); New Vmpolicy.builder (); Vmpolicybuilder.detectleakedsqlliteobjects (). Penaltylog (); if (Build.VERSION.SDK_INT >= version_codes. Honeycomb) { vmpolicybuilder.detectleakedclosableobjects (); } Strictmode.setvmpolicy (Vmpolicybuilder.build ());}
Special attention
- Strict mode should not be turned on when publishing a version
A solution to the symptoms without a cure
The following code allows strict mode to allow all disk operations and network operations. However, this does not change the real problem solving, the main thread still has network operation, may cause the program to appear unresponsive situation. So this is a bad solution, and the solution to the problem should be to move the network operation to a non-main thread, rather than this deceiving approach.
New StrictMode.ThreadPolicy.Builder (). Permitall (). build (); Strictmode.setthreadpolicy (policy);
P.s. This stupid method actually has a lot of people on the StackOverflow who think it is useful and difficult to understand.
Asynctask is not good.
First implement a method of requesting the network that we use to test
private void Dogetrequest () {HttpGet Method = new httpget ("http://droidyue.com" ); Abstract HttpClient http = new Defaulthttpclient (); try {httpresponse response =< Span style= "color: #000000;" > Http.execute (method); LOG.I (LogTag, "dogetrequest responsecode=" + response.getstatusline (). Getstatuscode () + "Threadinfo =" + Thread.CurrentThread ()); catch (Clientprotocolexceptione) { E.printstacktrace (); catch (Ioexceptione) { E.printstacktrace (); }}
You can avoid networkonmainthreadexception exceptions by using Asynctask to move network operations to Asynctask threads.
New Asynctask<void,integer,void>() {@Override protected Void doinbackground (void...params) { dogetrequest (); return NULL ; }}. Execute ();
The drawbacks of Asynctask
- The above asynctask is an anonymous inner class object, because the Java non-static inner class instance holds a reference to an external class instance, and the Asynctask instance holds a reference to the activity, which can easily cause a memory leak
- According to the official Android document spending, Asynctask is recommended to handle short (10 seconds) operations, which are local light-weight IO operations. It is not appropriate to use a time-varying operation such as a network.
For more details about Asynctask Please refer to the bad Asynctask in Android
That's not good.
Since Asynctask can lead to memory leaks and does not apply to long-time operations, then
Newvoid run () { super.run (); Dogetrequest (); }}.start ();
This is still not good enough, although the individual threads can handle long operations, but the problem remains
- Memory leak issues may still exist
- If you repeat this operation multiple times, it is not good to recreate the new thread each time.
Resolves a memory leak issue that could be caused by two of these internal classes
- The subclass of Asynctask or thread as a separate file, not holding a strong reference to activity
- If you use the static adornment for a subclass of Asynctask or thread, you do not implicitly hold an activity's strong reference
- In the case of an anonymous inner class, you need to set its object to a member property, and the static modifier does not implicitly hold a strong reference to the activity.
Solve the problem which strong
Solve the above-mentioned memory leaks can be achieved by a relatively perfect implementation, or use loaders implementation is also good. For thread reuse issues, you can use Executors.newsinglethreadexecutor () to resolve. Specific programmes are subject to availability.
Android.os.NetworkOnMainThreadException