Android-调用PHP脚本:只有创建视图层次结构的原始线程才能触摸它';的观点


Android- Calling PHP script: Only the original thread that created a view hierarchy can touch it's views?

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

我在Logcat:中得到了这个

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

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

注意:我已经看到了这个答案,但我不确定如何将它与我的特定代码联系起来。

安卓活动代码:

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 
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();

您不能从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);
        }
    });

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

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

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

再次,把这个放在你的线程中,你应该会没事的。