我正在从IntentService进行网络调用,但仍然收到NetworkOnMainThreadException。我的理解是IntentService总是在工作线程上运行,所以我很惊讶看到这一点。关键部分可能是我的IntentService正在调用执行网络调用的静态助手类。静态助手类在我的主Application类中实例化。
我认为这仍然会在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事件(显然在主线程上运行)调用的。
答案 0 :(得分:5)
我发现了这个问题。在上面的LoginService.java中查看这个令人困惑的覆盖:
@Override
public void onStart(Intent intent, int startId) {
onHandleIntent(intent);
}
这导致onHandleIntent
代码在主线程上运行,因为它是从onStart事件(显然在主线程上运行)调用的。我很想阅读开发人员的想法!
答案 1 :(得分:2)
你的怀疑是正确的。您正在从应用程序类中实例化NetworkUtils类。无论你怎么称呼它,它都不会在后台线程中运行。
答案 2 :(得分:2)
严格来说,它是一个包含静态变量的类。我强烈建议你避免使用静态变量。相反,使用Android API在SharedPreferences或Bundles等对象中保持状态。
Android对象环境设计很短暂。而不是将状态保存在内存中,而是将其保留在专门为其设计的对象和构造中,例如Bundles和SharedPreferences。你会更开心。尝试其他任何事情,你最终会试图将大量的蠕虫挤回一个非常小的罐子里。