NetworkOnMainThreadException в IntentService

Я делаю сетевые вызовы из IntentService, но все же получаю NetworkOnMainThreadException. Я понимаю, что IntentService всегда работает на рабочем потоке, поэтому я удивлен, увидев это. Ключевым моментом может быть то, что мой IntentService вызывает статический вспомогательный класс, который выполняет сетевые вызовы. Статический вспомогательный класс создается в моем основном классе приложения.

Я думал, что это все равно будет выполняться на рабочем потоке IntentService. Что мне не хватает?

Честно говоря, я предпочитаю пьянящие информативные дискуссии по быстрому исправлению кода. Но если код необходим, то код должен быть предоставлен:

//MyApplication.java public class MyApplication extends Application{ private static NetworkUtils utils; @Override public void onCreate() { super.onCreate(); utils = new NetworkUtils(this); ... } ... } //NetworkUtils.java public class NetworkUtils { private static Context context; private static final Gson gson = new Gson(); public NetworkUtils(Context context) { this.context = context; } public static final DataResponse login(String email, String password) { //*** NetworkOnMainThreadException OCCURS HERE *** DataResponse response = HttpConnection.put(url, json); ... return response; } ... } //LoginService.java public class LoginService extends IntentService { public LoginService() { super("LoginService"); } @Override public void onStart(Intent intent, int startId) { onHandleIntent(intent); } @Override protected void onHandleIntent(Intent intent) { Bundle bundle = new Bundle(); DataResponse response = NetworkUtils.login(email, password); ... bundle.putBoolean(MyConstants.ExtraKeys.LOGGED, response.success); MainApplication.getApplicationInstance().sendBroadCast(MyConstants.Actions.LOGIN, bundle); } } //LoginActivity.java public class LoginActivity extends ActionBarActivity implements IDialogClickListener { ... public void onLoginButtonPressed() { Intent intent = new Intent(MainApplication.getApplicationInstance(), LoginService.class); this.startService(intent); } } 

Кроме того, Logcat:

 > 04-01 18:20:41.048: VERBOSE/com.foo.foo(28942): > com.foo.foo.network.HttpConnection.execute - METHOD: PUT > 04-01 18:20:41.068: ERROR/com.foo.foo(28942): > com.foo.foo.social.NetworkUtils.login - class > android.os.NetworkOnMainThreadException: null > 04-01 18:20:41.169: DEBUG/com.foo.foo(28942): > com.foo.foo.MainActivity$MyReceiver.onReceive - BROADCAST RECEIVED: > com.foo.foo.MainApplication@422d81d8 - Intent { act=com.foo.foo.login > dat=com.foo.foo.scheme://data/1364854841079 (has extras) } > 04-01 18:20:41.169: INFO/com.foo.foo(28942): > com.foo.foo.activity.LoginActivity.setData - ACTION: com.foo.foo.login > - ISERROR: true 

РЕШЕНИЕ

Основная проблема была немного устаревшего кода, который вызывал onHandleIntent явно. В LoginService.java выше:

 @Override public void onStart(Intent intent, int startId) { onHandleIntent(intent); } 

Это приводит к тому, что код onHandleIntent запускается в основном потоке, так как он вызывается из события onStart (который, по-видимому, работает в основном потоке).

Я заметил эту проблему. Проверьте это недоумение в LoginService.java выше:

 @Override public void onStart(Intent intent, int startId) { onHandleIntent(intent); } 

Это приводит к onHandleIntent код onHandleIntent запускается в основном потоке, так как он вызывается из события onStart (который, по-видимому, работает в основном потоке). Я хотел бы прочитать ум разработчика, который положил это!

Ваши подозрения верны. Вы создаете класс NetworkUtils из своего класса приложения. Это не будет работать в фоновом потоке, как бы вы это ни называли.

Строго говоря, это класс, содержащий статические переменные. Я настоятельно рекомендую избегать статических переменных. Вместо этого используйте Android API для сохранения состояния в таких объектах, как SharedPreferences или Bundles.

Объектная среда Android является временной по дизайну. Вместо сохранения состояния в памяти сохраняйте его в объектах и ​​конструкциях, специально предназначенных для него, таких как Bundles и SharedPreferences. Вы будете намного счастливее. Попробуйте что-нибудь еще, и вы в конечном итоге попытаетесь выжать большую массу червей обратно в очень маленькую банку.