我正在尝试使用下面显示的代码在我的服务器上调用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
答案 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);
}
});
再次,把它放在你的线程中,你应该没问题。