我正试图使用下面显示的代码在服务器上调用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);
}
});
再次,把这个放在你的线程中,你应该会没事的。