首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NetworkOnMainThreadException in IntentService

NetworkOnMainThreadException in IntentService
EN

Stack Overflow用户
提问于 2013-04-01 22:54:37
回答 3查看 2K关注 0票数 9

我正在从一个IntentService打网络电话,但仍然收到一个NetworkOnMainThreadException。我的理解是,IntentService总是运行在一个工作线程上,所以我很惊讶地看到了这一点。关键的部分可能是我的IntentService正在调用一个执行网络调用的静态助手类。静态助手类在我的主应用程序类中实例化。

我认为这仍然会在IntentService的工作线程上执行。我遗漏了什么?

老实说,比起快速的代码修复,我更喜欢内容丰富的讨论。但如需要编码,则应提供下列代码:

代码语言:javascript
复制
//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:

代码语言:javascript
复制
> 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中:

代码语言:javascript
复制
@Override 
public void onStart(Intent intent, int startId) { 
    onHandleIntent(intent); 
} 

这导致onHandleIntent代码在主线程上运行,因为它是从onStart事件(显然是在主线程上运行)调用的。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-06-12 21:30:15

我注意到了这个问题。请查看上面LoginService.java中的这个令人困惑的覆盖:

代码语言:javascript
复制
@Override 
public void onStart(Intent intent, int startId) { 
    onHandleIntent(intent); 
} 

这导致onHandleIntent代码在主线程上运行,因为它是从onStart事件(显然是在主线程上运行)调用的。我想读一读开发人员的想法,谁把它放进去!

票数 5
EN

Stack Overflow用户

发布于 2013-04-02 00:03:25

你的怀疑是正确的。您正在从应用程序类实例化NetworkUtils类。不管你怎么称呼它,它都不会在后台线程中运行。

票数 2
EN

Stack Overflow用户

发布于 2013-04-02 00:45:53

严格地说,它是一个包含静态变量的类。我强烈建议您避免静态变量。相反,使用Android在对象(如SharedPreferences或Bundles )中持久化状态。

Android对象环境在设计上是暂时性的。不要在内存中持久化状态,而是将其保存在专门为其设计的对象和构造中,例如Bundles和SharedPreferences。你会更开心的。再试一试,你就会试图把一大群蠕虫挤回一个很小的罐子里。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15753316

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档