1

我正在运行一个简单的项目,点击 android 中的按钮。显示一条从 web 服务返回的消息,该 web 服务的编码是在 java 中完成的。

这是我在 eclipse for Android 中的程序:

@Override
public void onClick(View v) {
    final String url = "http://10.0.2.2:8050/WebPractice/PracticeWebServices?wsdl";
    final String namespace = "http://PracticeWebServices/";
    final String methodName = "hello";
    final String action = namespace + methodName;

    if(v.getId() == submit_btn.getId()) {
        SoapObject so = new SoapObject(namespace, methodName);
        so.addProperty("name", "Arjun");
        SoapSerializationEnvelope sse = new SoapSerializationEnvelope(SoapEnvelope.VER11);
        sse.setOutputSoapObject(so);
        HttpTransportSE hse = new HttpTransportSE(url);

        try {
            hse.call(action, sse);
            SoapPrimitive primitive = (SoapPrimitive)sse.getResponse();
            Toast.makeText(getApplicationContext(),primitive.toString() , Toast.LENGTH_SHORT);
        } catch(IOException e) {
            e.printStackTrace();
        } catch (XmlPullParserException e) {
            e.printStackTrace();
        }
    }
}

以下是我的 Java 代码:

@WebService(serviceName = "PracticeWebServices")
public class PracticeWebServices {

    @WebMethod(operationName = "hello")
    public String hello(@WebParam(name = "name") String name) {
        return "Hello " + name + " !";
    }
}

我已经在清单文件中包含了互联网权限......

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

现在,当我在 Eclipse 提供的模拟器中运行该文件时。单击按钮时,它会向我显示一条消息Unfortunately the program has stopped

当我检查 logCat....似乎我在android.os.NetworkOnMainThreadException遇到异常

4

5 回答 5

2

您不应该在主线程中调用长时间保持进程,例如互联网资源、磁盘上的数据……您应该使用后台任务。否则,您将遇到 ANR 错误或编译错误,就像您提到的那样。

于 2013-01-15T17:55:44.613 回答
2

这里的问题很简单,您需要在单独的线程上进行 Web 服务调用(或你有什么)。因此,很简单,您需要研究如何使用 Android 进行线程处理。不幸的是,这可能有点痛苦,因为您需要在单独的线程上进行服务调用,但您需要在主线程上更新 UI。通常这需要在线程之间传递数据,这涉及处理程序或其他复杂性。幸运的是,Android 平台提供了 Async Task 来处理这个问题,这减轻了一些复杂性,并且可以帮助您避免代码中的一些混乱。

将网络调用迁移到线程(或 Android 的异步任务)的有用文档

无痛线程(来自 Android 开发者文档) 异步任务(来自 Android 开发者文档) Android 线程、处理程序和 AsyncTask – 响应性设计教程(来自 Android 开发者文档)

于 2013-01-15T17:57:30.913 回答
2

您应该将长时间的网络获取操作放在 aThreadAsyncTask

我建议你使用AsyncTask

class你可以通过创建一个that来做这样的事情extends AsyncTask

private class LongNetworkOperation extends AsyncTask<String, Void, String> {

    @Override
    protected String doInBackground(String... params) {

        SoapObject so = new SoapObject(namespace, methodName);
        so.addProperty("name", "Arjun");
        SoapSerializationEnvelope sse = new SoapSerializationEnvelope(SoapEnvelope.VER11);
        sse.setOutputSoapObject(so);
        HttpTransportSE hse = new HttpTransportSE(url);

        try {
            hse.call(action, sse);
            SoapPrimitive primitive = (SoapPrimitive)sse.getResponse();
            Toast.makeText(getApplicationContext(),primitive.toString() , Toast.LENGTH_SHORT);
        } catch(IOException e) {
            e.printStackTrace();
        } catch (XmlPullParserException e) {
            e.printStackTrace();
        }
    }
}

你可以这样称呼onClick()

@Override
public void onClick(View v) {
    if(v.getId()==submit_btn.getId()) {
        new LongNetworkOperation.execute();
    }
}

另外,我建议您显示一个ProgressDialogonPreExecute()隐藏它,onPostExecute()以便用户了解长时间的后台进程,强烈建议长时间操作

于 2013-01-16T15:40:14.853 回答
1

您不应该在主线程上运行网络请求,这会导致NetworkOnMainThreadException. 使用自定义查看此解决方案AsyncTask或使用以下库之一:

于 2013-01-15T17:59:39.457 回答
1

您遇到的问题是您尝试执行的网络操作不能也不应该在主 UI 线程上执行。这样做会导致ANR (Android Not Responding),这正是您刚刚遇到的错误。您想要做的是将您的代码移动到一个单独的线程,或者移动到一个AsyncTask将在不同线程的后台执行此操作的doInBackground()方法,该方法无法访问您在主 UI 线程上的视图。例如,

private class ExampleOperation extends AsyncTask<String, Void, String> {

    public ExampleOperation() { //ctor }

    @Override
    protected void onPreExecute() {
        // things that you want to initialize and maybe show dialog to user.
    }

    @Override
    protected String doInBackground(String... params) {
       // this is where you perform that network related operation.  
    }

    @Override
    protected void onPostExecute(String result) {
       // this is where get the results from the network related task.
    }

    @Override
    protected void onProgressUpdate(Void... values) {
       // you can update your progressbar if any; otherwise omit method.
    }

}

然后你所要做的就是在你想使用它的地方调用 AsyncTask:new ExampleOperation().execute();

于 2013-01-15T18:02:11.513 回答