我想掌握从url解析json内容所以我尝试了一个小练习。我创建了一个小应用程序。我的第一步是从网址获取内容。当应用程序“停止工作”时我卡住了,而logcat没有任何线索显示我错在哪里。
的活动:
包tri.jsonparser;
//import...
public class MainActivity extends Activity {
URL url;
HttpURLConnection conn;
String str;
Button btn;
TextView content;
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn = (Button) findViewById(R.id.button);
content = (TextView) findViewById(R.id.textContent);
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
try {
url = new URL("http://thinktodo.net/LocationServiceSystem/index.php/location/getLocation?username=1");
conn = (HttpURLConnection) url.openConnection();
Log.d("my tag", "connection ok");
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
Log.d("my tag", "reader ok");
str = br.readLine();
content.setText(str);
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
}
activity_main.xml中:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/textViewLat"
android:layout_centerHorizontal="true"
android:layout_marginTop="118dp"
android:text="Get content" />
<TextView
android:id="@+id/textContent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginTop="58dp"
android:text="Content"
android:textAppearance="?android:attr/textAppearanceLarge" />
</RelativeLayout>
logcat的:
04-22 16:24:42.365: E/cutils-trace(1456): Error opening trace file: No such file or directory (2)
04-22 16:24:42.421: E/memtrack(1456): Couldn't load memtrack module (No such file or directory)
04-22 16:24:42.421: E/android.os.Debug(1456): failed to load memtrack module: -2
04-22 16:24:42.737: E/cutils-trace(1467): Error opening trace file: No such file or directory (2)
04-22 16:24:42.789: E/memtrack(1467): Couldn't load memtrack module (No such file or directory)
04-22 16:24:42.789: E/android.os.Debug(1467): failed to load memtrack module: -2
04-22 16:24:43.093: E/OpenGLRenderer(1478): Getting MAX_TEXTURE_SIZE from GradienCache
04-22 16:24:43.101: E/OpenGLRenderer(1478): MAX_TEXTURE_SIZE: 8192
04-22 16:24:43.145: E/OpenGLRenderer(1478): Getting MAX_TEXTURE_SIZE from Caches::initConstraints()
04-22 16:24:43.149: E/OpenGLRenderer(1478): MAX_TEXTURE_SIZE: 8192
04-22 16:24:45.297: E/AndroidRuntime(1478): FATAL EXCEPTION: main
04-22 16:24:45.297: E/AndroidRuntime(1478): Process: tri.jsonparser, PID: 1478
04-22 16:24:45.297: E/AndroidRuntime(1478): android.os.NetworkOnMainThreadException
04-22 16:24:45.297: E/AndroidRuntime(1478): at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1145)
04-22 16:24:45.297: E/AndroidRuntime(1478): at java.net.InetAddress.lookupHostByName(InetAddress.java:385)
04-22 16:24:45.297: E/AndroidRuntime(1478): at java.net.InetAddress.getAllByNameImpl(InetAddress.java:236)
04-22 16:24:45.297: E/AndroidRuntime(1478): at java.net.InetAddress.getAllByName(InetAddress.java:214)
04-22 16:24:45.297: E/AndroidRuntime(1478): at com.android.okhttp.internal.Dns$1.getAllByName(Dns.java:28)
04-22 16:24:45.297: E/AndroidRuntime(1478): at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:216)
04-22 16:24:45.297: E/AndroidRuntime(1478): at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:122)
04-22 16:24:45.297: E/AndroidRuntime(1478): at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:292)
04-22 16:24:45.297: E/AndroidRuntime(1478): at com.android.okhttp.internal.http.HttpEngine.sendSocketRequest(HttpEngine.java:255)
04-22 16:24:45.297: E/AndroidRuntime(1478): at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:206)
04-22 16:24:45.297: E/AndroidRuntime(1478): at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:345)
04-22 16:24:45.297: E/AndroidRuntime(1478): at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:296)
04-22 16:24:45.297: E/AndroidRuntime(1478): at com.android.okhttp.internal.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:179)
04-22 16:24:45.297: E/AndroidRuntime(1478): at tri.jsonparser.MainActivity$1.onClick(MainActivity.java:41)
04-22 16:24:45.297: E/AndroidRuntime(1478): at android.view.View.performClick(View.java:4438)
04-22 16:24:45.297: E/AndroidRuntime(1478): at android.view.View$PerformClick.run(View.java:18422)
04-22 16:24:45.297: E/AndroidRuntime(1478): at android.os.Handler.handleCallback(Handler.java:733)
04-22 16:24:45.297: E/AndroidRuntime(1478): at android.os.Handler.dispatchMessage(Handler.java:95)
04-22 16:24:45.297: E/AndroidRuntime(1478): at android.os.Looper.loop(Looper.java:136)
04-22 16:24:45.297: E/AndroidRuntime(1478): at android.app.ActivityThread.main(ActivityThread.java:5017)
04-22 16:24:45.297: E/AndroidRuntime(1478): at java.lang.reflect.Method.invokeNative(Native Method)
04-22 16:24:45.297: E/AndroidRuntime(1478): at java.lang.reflect.Method.invoke(Method.java:515)
04-22 16:24:45.297: E/AndroidRuntime(1478): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
04-22 16:24:45.297: E/AndroidRuntime(1478): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
04-22 16:24:45.297: E/AndroidRuntime(1478): at dalvik.system.NativeStart.main(Native Method)
04-22 16:24:48.121: E/InputDispatcher(547): channel '52a395b4 tri.jsonparser/tri.jsonparser.MainActivity (server)' ~ Channel is unrecoverably broken and will be disposed!
答案 0 :(得分:1)
您需要在Runnable中实现连接并在另一个线程上运行它。这是因为Android不允许您在UI线程上执行网络请求(这是您在活动中默认使用的)。 Android执行此操作,因为您的网络请求可能需要很长时间才能返回,并且UI线程的执行在此之前停止(“阻止”)。 尝试使用下面的代码替换你的btn.setOnClickListener()。
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Runnable r = new Runnable(){
@Override
public void run(){
try {
url = new URL("http://thinktodo.net/LocationServiceSystem/index.php/location/getLocation?username=1");
conn = (HttpURLConnection) url.openConnection();
Log.d("my tag", "connection ok");
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
Log.d("my tag", "reader ok");
str = br.readLine();
Runnable uir = new Runnable(){
@Override
public void run()
{
content.setText(str);
}
};
MainActivity.this.runOnUiThread(uir);
br.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
Thread th = new Thread(r);
th.start();
}
});
一旦您的请求与服务器建立连接,TextView的内容就会发生变化。 编辑:正如@ njzk2指出的那样,设置TextView的内容必须在UI线程上进行。