Intereting Posts
Программирование на (не * для *) устройства Android Как центрировать & left & right выравнивать значки ActionBar в Android Как удалить стандартную белую границу выпадающего списка Что такое (D / NSD: curPkgName отсутствует в списке)? Error: Ошибка: ресурс не найден, который соответствует указанному имени: attr 'colorAccent' Android OpenGL ES искаженное изображение Вопрос в Android Fragment: по-прежнему нажмите на предыдущий фрагмент Загрузка собственной общей библиотеки из другого приложения для Android Android – как получить или установить (распечатать) DPI (точек на дюйм) файла JPEG при загрузке или сохранении программно? Получите собственный номер телефона в андроиде (многие проблемы протестированы, но не сработали)? Строить андроид с clang вместо gcc? И clang stl lib вместо gnustl lib? Лучший способ показать индикатор загрузки / выполнения? Создание панорамного сферического вида в картоне андроида Qt Creator 3.2.1, включая .jar для Android Что такое BroadcastReceiver и когда мы его используем?

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. Вы будете намного счастливее. Попробуйте что-нибудь еще, и вы в конечном итоге попытаетесь выжать большую массу червей обратно в очень маленькую банку.