12

在我的 Android 应用程序的 Service 类中调用 REST WebService 会创建NetworkOnMainThreadException.

我理解为什么会在 Activity 中引发此异常:通过网络同步获取某些内容是一种非常糟糕的做法,但我很惊讶在服务类中看到同样的错误。所以我的问题是:

- 在这种特定情况下,我应该使用StrictMode.setThreadPolicy()来允许这个调用。(对于那些因为在活动中遇到此错误而阅读此内容的人,请不要使用 StrictMode 隐藏此错误,请使用 AsyncTask)

- 或者我应该使用 AsyncTask 吗?在那种情况下,这里有什么问题?线程上的服务不是与 Activity 的服务分开的吗?

4

2 回答 2

18

尽管Service用于后台处理,但它们在主线程中运行。

来自文档的简短引用:

注意:默认情况下,服务与声明它的应用程序在同一进程中运行,并且在该应用程序的主线程中运行。因此,如果您的服务在用户与来自同一应用程序的活动交互时执行密集或阻塞操作,则该服务将降低活动性能。为避免影响应用程序性能,您应该在服务内启动一个新线程。

“后台处理”意味着服务没有用户界面,即使用户没有直接与应用程序交互,它也可以运行。但是默认情况下,所有后台处理仍然发生在主线程中。

那么,如何解决它并摆脱异常呢?正如文档所建议的,您必须使用后台线程。在您的服务中,您可以AsyncTask直接使用或创建线程。但我想 IntentService可能最适合您的情况。IntentService在后台线程中处理请求(这就是您正在寻找的那种服务)。

于 2012-08-09T00:06:34.880 回答
0

服务在主线程中运行,这就是为什么你需要做类似的事情

public class ServiceDownloadSomething extends Service {

private static final String TAG = ServiceDownloadSomething.class.getSimpleName();

private boolean isRunning;
private Thread backgroundThread;

private Runnable myTask = new Runnable() {
    public void run() {
        while (true) {

            //sleep 30 seconds
            long sleepTime = System.currentTimeMillis() + (15 * 1000);

            try {
                Thread.sleep(sleepTime - System.currentTimeMillis());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            try {
                //perform network action
                downloadSomething();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
};

@Nullable
@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public void onCreate() {
    this.isRunning = false;
    this.backgroundThread = new Thread(myTask);
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    if(!this.isRunning) {
        this.isRunning = true;
        this.backgroundThread.start();
    }

    return START_STICKY;
}

@Override
public void onDestroy() {
    this.isRunning = false;
}

private void downloadSomething() throws IOException {

    URL url = new URL("http://192.168.197.101:8080/api/medias/");
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setReadTimeout(10000 /* milliseconds */);
    conn.setConnectTimeout(15000 /* milliseconds */);
    conn.setRequestMethod("POST");
    conn.setDoInput(true);
    // Starts the query
    conn.connect();

    InputStream is = conn.getInputStream();
    StringBuilder sb = new StringBuilder();
    int r;
    do {
        r = is.read();

        if (r != -1){
            sb.append((char) r);
        }

    } while (r != -1);

    String json = sb.toString();
    Log.d(TAG, json);

}

}

于 2018-04-19T18:47:19.460 回答