Android-调用PHP脚本:只有创建视图层次结构的原始线程才能触及它的视图?

时间:2014-08-07 19:07:43

标签: php android textview

我正在尝试使用下面显示的代码在我的服务器上调用PHP脚本。这段代码给了我非常奇怪的结果。有时它会显示PHP命令所需的结果,但9/10它只显示一个空白屏幕。

我在Logcat中得到这个:

Only the original thread that created a view hierarchy can touch it's views?

如何更改代码以始终显示结果?

注意:我看过this answer,但我不确定如何将其与我的特定代码联系起来。

Android活动代码:

public class SimpleServer extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {


        super.onCreate(savedInstanceState);
        setContentView(R.layout.simpleserver);

        final TextView testView= (TextView)findViewById(R.id.tvSimpleServer);



        Thread thread = new Thread(new Runnable(){
            @Override
            public void run() {
                try {
                    Log.d("start", "start");

                    String link = "http://www.cs.qub.ac.uk/40006697/server2.php?command=getAnimalSound&animal=bird";



                    try {
                        URL url = new URL(link);
                    } catch (MalformedURLException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    HttpClient client = new DefaultHttpClient();


                    HttpGet request = new HttpGet();
                    try {

                        request.setURI(new URI(link));

                    } catch (URISyntaxException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    Log.d("abouttorequest", "about to req");
                    HttpResponse response = null;

                    try {
                        response = client.execute(request);
                        Log.d("afterrequest", "after req");
                    } catch (Exception e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();

                    }
                    try {
                        BufferedReader in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));

                        //String test= in.toString();



                         String line;
                            while ((line = in.readLine()) != null) {

                                testView.setText("Response:  " + line);
                            }

                        Log.d("testingscript", "hello");
                    } catch (IllegalStateException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }



                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        thread.start(); 





    }


}

Logcat报告(请注意,在req之后需要req等跟踪代码日志):

08-07 20:07:02.646: D/AbsListView(10298): onVisibilityChanged() is called, visibility : 0
08-07 20:07:02.646: D/AbsListView(10298): unregisterIRListener() is called 
08-07 20:07:02.666: D/AbsListView(10298): unregisterIRListener() is called 
08-07 20:07:03.487: D/AbsListView(10298): unregisterIRListener() is called 
08-07 20:07:03.487: W/ApplicationPackageManager(10298): getCSCPackageItemText()
08-07 20:07:03.517: D/start(10298): start
08-07 20:07:03.517: D/abouttorequest(10298): about to req
08-07 20:07:03.637: D/afterrequest(10298): after req
08-07 20:07:03.637: W/System.err(10298): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
08-07 20:07:03.637: W/System.err(10298):    at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6909)
08-07 20:07:03.637: W/System.err(10298):    at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:1054)
08-07 20:07:03.637: W/System.err(10298):    at android.view.View.requestLayout(View.java:17321)
08-07 20:07:03.637: W/System.err(10298):    at android.view.View.requestLayout(View.java:17321)
08-07 20:07:03.647: W/System.err(10298):    at android.view.View.requestLayout(View.java:17321)
08-07 20:07:03.647: W/System.err(10298):    at android.view.View.requestLayout(View.java:17321)
08-07 20:07:03.647: W/System.err(10298):    at android.view.View.requestLayout(View.java:17321)
08-07 20:07:03.647: W/System.err(10298):    at android.widget.TextView.checkForRelayout(TextView.java:8003)
08-07 20:07:03.647: W/System.err(10298):    at android.widget.TextView.setText(TextView.java:4840)
08-07 20:07:03.647: W/System.err(10298):    at android.widget.TextView.setText(TextView.java:4672)
08-07 20:07:03.647: W/System.err(10298):    at android.widget.TextView.setText(TextView.java:4647)
08-07 20:07:03.647: W/System.err(10298):    at com.example.brianapp.SimpleServer$1.run(SimpleServer.java:103)
08-07 20:07:03.647: W/System.err(10298):    at java.lang.Thread.run(Thread.java:841)
08-07 20:07:03.938: D/AbsListView(10298): onVisibilityChanged() is called, visibility : 4
08-07 20:07:03.938: D/AbsListView(10298): unregisterIRListener() is called 

3 个答案:

答案 0 :(得分:0)

testView.setText("Response:  " + line);

你不能这样做是因为你正在运行一个新线程,而这个线程无法与'main'或GUI线程交互。我建议你使用异步任务。

//our async task for sending web requests
    private class SendHttpRequest extends AsyncTask<Objct, Void, String> {
        String responseBack = "";

        @Override
        protected String doInBackground(Object... args) {

            try {
                Log.d("start", "start");

                String link = "http://www.cs.qub.ac.uk/40006697/server2.php?command=getAnimalSound&animal=bird";



                try {
                    URL url = new URL(link);
                } catch (MalformedURLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                HttpClient client = new DefaultHttpClient();


                HttpGet request = new HttpGet();
                try {

                    request.setURI(new URI(link));

                } catch (URISyntaxException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                Log.d("abouttorequest", "about to req");
                HttpResponse response = null;

                try {
                    response = client.execute(request);
                    Log.d("afterrequest", "after req");
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();

                }
                try {
                    BufferedReader in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));

                    //String test= in.toString();



                     String line;
                        while ((line = in.readLine()) != null) {

                            //testView.setText("Response:  " + line);//replace with
                            responseBack = line;
                        }

                    Log.d("testingscript", "hello");
                } catch (IllegalStateException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }



            } catch (Exception e) {
                e.printStackTrace();
            }
          return responseBack;
        }

        @Override
        protected void onPostExecute(String result) {
           testView.setText("Response:  " + result);
        }
    }

然后你就可以在任何地方调用它。

new SendHttpRequest().execute();

答案 1 :(得分:0)

您无法从除UI线程之外的线程编辑任何UI组件(创建UI内容​​的线程)包裹您的代码,如

        final String data = line;
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                testView.setText("Response:  " + data);
            }
        });

    final String data = line;
    testView.post(new Runnable() {
        @Override
        public void run() {
            testView.setText("Response:  " + data);
        }
    });

答案 2 :(得分:0)

有两种方法可以处理这种事情。首先是在AsyncTask中进行网络连接,然后使用内置的onPostExecute方法将调用结果传递回main方法。

另一种是在现有线程中创建一个线程。由于您尝试在testView对象中设置文本,因此可以执行以下操作:

testView.post(new Runnable() {
    public void run() {
        testView.setText("Response:  " + line);
    }
});

再次,把它放在你的线程中,你应该没问题。