9

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 イベント (明らかにメイン スレッドで実行される) から呼び出されるため、メイン スレッドで実行されます。

4

3 に答える 3

5

私は問題を発見しました。上記の LoginService.java の不可解なオーバーライドを確認してください。

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

これにより、onHandleIntentコードは onStart イベント (明らかにメイン スレッドで実行される) から呼び出されるため、メイン スレッドで実行されます。それを入れた開発者の心を読んでみたいです!

于 2013-06-12T21:30:15.033 に答える
2

あなたの疑いは正しいです。アプリケーション クラスから NetworkUtils クラスをインスタンス化しています。どのように呼び出しても、バックグラウンド スレッドでは実行されません。

于 2013-04-02T00:03:25.107 に答える
2

厳密には、静的変数を含むクラスです。静的変数を避けることを強くお勧めします。代わりに、Android API を使用して、SharedPreferences や Bundles などのオブジェクトの状態を保持します。

Android オブジェクト環境は、設計上一時的なものです。状態をメモリに永続化する代わりに、Bundle や SharedPreferences など、そのために特別に設計されたオブジェクトやコンストラクトに永続化します。あなたはもっと幸せになるでしょう。他の方法を試してみると、大量のミミズを非常に小さな缶に押し戻そうとすることになります。

于 2013-04-02T00:45:53.397 に答える