在 Fragments 中使用 JSON 时,应用在 Android 开发中没有响应

Posted

技术标签:

【中文标题】在 Fragments 中使用 JSON 时,应用在 Android 开发中没有响应【英文标题】:When using JSON in Fragments the app is not responding in Android Development 【发布时间】:2014-01-12 08:32:20 【问题描述】:

我在 android 中使用导航抽屉。我通过 JSON 从 URL 获取数据。当我在加载片段时运行应用程序时出现错误提示

“很遗憾,App 没有回应” 我从 php 文件中获取 JSON 数据,它是从 INTERNET 获取的,现在它位于 localhost 中。

我的片段类是:

import java.util.ArrayList;
import java.util.HashMap;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;


public class QMFragment extends Fragment 



public QMFragment()

    // url to make request
    private static String url = "http://localhost/app/qm_data.php";

    // JSON Node names
    private static final String TAG_QM = "qm";
    private static final String TAG_ID = "id";
    private static final String TAG_NAME = "name";
    private static final String TAG_URL = "url";

    // Hashmap for ListView
    ArrayList<HashMap<String, String>> contactList = new ArrayList<HashMap<String, String>>();

    // JSONArray
    JSONArray qmArray = null;

    // Creating JSON Parser instance
    JSONParser jParser = new JSONParser();

    // getting JSON string from URL
    JSONObject json = jParser.getJSONFromUrl(url);


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) 


        View rootView = inflater.inflate(R.layout.fragment_qm, container, false);


        getData(); 


        return rootView;
    

    public void getData()
        try 
            // Getting Array
            qmArray = json.getJSONArray(TAG_QM);

            // looping through All Data
            for(int i = 0; i < qmArray.length(); i++)
                JSONObject c = qmArray.getJSONObject(i);

                // Storing each json item in variable
                String id = c.getString(TAG_ID);
                String name = c.getString(TAG_NAME);
                String url = c.getString(TAG_URL);

             // creating new HashMap
                HashMap<String, String> map = new HashMap<String, String>();

                // adding each child node to HashMap key => value
                map.put(TAG_ID, id);
                map.put(TAG_NAME, name);
                map.put(TAG_URL, url);


                // adding HashList to ArrayList
                contactList.add(map);

            
         catch (JSONException e) 
            e.printStackTrace();
        

    


我的 JSONParser.java 是:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

public class JSONParser 

    static InputStream is = null;
    static JSONObject jObj = null;
    static String json = "";

    // constructor
    public JSONParser() 

    

    public JSONObject getJSONFromUrl(String url) 

        // Making HTTP request
        try 
            // defaultHttpClient
            DefaultHttpClient httpClient = new DefaultHttpClient();
            HttpPost httpPost = new HttpPost(url);

            HttpResponse httpResponse = httpClient.execute(httpPost);
            HttpEntity httpEntity = httpResponse.getEntity();
            is = httpEntity.getContent();           

         catch (UnsupportedEncodingException e) 
            e.printStackTrace();
         catch (ClientProtocolException e) 
            e.printStackTrace();
         catch (IOException e) 
            e.printStackTrace();
        

        try 
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                    is, "iso-8859-1"), 8);
            StringBuilder sb = new StringBuilder();
            String line = null;
            while ((line = reader.readLine()) != null) 
                sb.append(line + "\n");
            
            is.close();
            json = sb.toString();
         catch (Exception e) 
            Log.e("Buffer Error", "Error Converting Result " + e.toString());
        

        // try parse the string to a JSON object
        try 
            jObj = new JSONObject(json);
         catch (JSONException e) 
            Log.e("JSON Parser", "Error Parsing Data " + e.toString());
        

        // return JSON String
        return jObj;

    

我的 XML 是:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_
    android:background="@color/bg" >

    <TextView
        android:id="@+id/txtLabel"
        android:layout_
        android:layout_
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="40dp"
        android:layout_marginTop="5dp"
        android:text="@string/head"
        android:textColor="@color/text_color"
        android:textSize="25sp" />

    <TextView
        android:layout_
        android:layout_
        android:layout_alignParentLeft="true"
        android:layout_below="@+id/txtLabel"
        android:layout_marginTop="5dp"
        android:background="#CCCCCC" />

    <ScrollView
        android:id="@+id/scrollView1"
        android:layout_
        android:layout_
        android:layout_below="@+id/txtLabel"
        android:layout_marginTop="10dp" >

        <RelativeLayout
            android:id="@+id/navigate_RLayout"
            android:layout_
            android:layout_ >

            <TextView
                android:id="@+id/txtqmhead"
                android:layout_
                android:layout_
                android:text="@string/qm_heading"
                android:textSize="25sp"
                android:textColor="@color/text_color" />
            <TextView
                android:id="@+id/txtqmsub"
                android:layout_
                android:layout_
                android:text="@string/qm_chn"
                android:textSize="18sp"
                android:textColor="@color/text_color"
                android:layout_below="@+id/txtqmhead"
                android:layout_marginLeft="28dp" />

            <TableLayout
                android:id="@+id/tbl"
                android:layout_
                android:layout_
                android:layout_alignParentLeft="true"
                android:layout_alignParentRight="true"
                android:layout_below="@+id/txtqmsub"
                android:layout_marginTop="20dp" >


             </TableLayout>

        </RelativeLayout>
    </ScrollView>

</RelativeLayout>

PHP 文件是:

<?php
    header('Content-type: application/json');

    $server = "localhost";
    $username = "root";
    $password = "";
    $db = "test";


$con = mysql_connect("localhost",$username,$password);
if (!$con)
  
  die('Could not connect: ' . mysql_error());
  
mysql_select_db($db, $con);

$result = mysql_query("SELECT * FROM example ORDER BY date DESC");

while($row = mysql_fetch_assoc($result))
  
        $output['qm'][]=$row;
  

print(json_encode($output));

mysql_close($con);


?>

LogCat:

12-24 10:19:54.322: E/AndroidRuntime(1700): FATAL EXCEPTION: main
12-24 10:19:54.322: E/AndroidRuntime(1700): android.os.NetworkOnMainThreadException
12-24 10:19:54.322: E/AndroidRuntime(1700):     at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1084)
12-24 10:19:54.322: E/AndroidRuntime(1700):     at java.net.InetAddress.lookupHostByName(InetAddress.java:391)
12-24 10:19:54.322: E/AndroidRuntime(1700):     at java.net.InetAddress.getAllByNameImpl(InetAddress.java:242)
12-24 10:19:54.322: E/AndroidRuntime(1700):     at java.net.InetAddress.getAllByName(InetAddress.java:220)
12-24 10:19:54.322: E/AndroidRuntime(1700):     at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:137)
12-24 10:19:54.322: E/AndroidRuntime(1700):     at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
12-24 10:19:54.322: E/AndroidRuntime(1700):     at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
12-24 10:19:54.322: E/AndroidRuntime(1700):     at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360)
12-24 10:19:54.322: E/AndroidRuntime(1700):     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
12-24 10:19:54.322: E/AndroidRuntime(1700):     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
12-24 10:19:54.322: E/AndroidRuntime(1700):     at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
12-24 10:19:54.322: E/AndroidRuntime(1700):     at com.qrodsintegrated.JSONParser.getJSONFromUrl(JSONParser.java:38)
12-24 10:19:54.322: E/AndroidRuntime(1700):     at com.qrodsintegrated.QMFragment.<init>(QMFragment.java:41)
12-24 10:19:54.322: E/AndroidRuntime(1700):     at com.qrodsintegrated.MainActivity.displayView(MainActivity.java:175)
12-24 10:19:54.322: E/AndroidRuntime(1700):     at com.qrodsintegrated.MainActivity.access$0(MainActivity.java:164)
12-24 10:19:54.322: E/AndroidRuntime(1700):     at com.qrodsintegrated.MainActivity$SlideMenuClickListener.onItemClick(MainActivity.java:126)
12-24 10:19:54.322: E/AndroidRuntime(1700):     at android.widget.AdapterView.performItemClick(AdapterView.java:292)
12-24 10:19:54.322: E/AndroidRuntime(1700):     at android.widget.AbsListView.performItemClick(AbsListView.java:1058)
12-24 10:19:54.322: E/AndroidRuntime(1700):     at android.widget.AbsListView$PerformClick.run(AbsListView.java:2514)
12-24 10:19:54.322: E/AndroidRuntime(1700):     at android.widget.AbsListView$1.run(AbsListView.java:3168)
12-24 10:19:54.322: E/AndroidRuntime(1700):     at android.os.Handler.handleCallback(Handler.java:605)
12-24 10:19:54.322: E/AndroidRuntime(1700):     at android.os.Handler.dispatchMessage(Handler.java:92)
12-24 10:19:54.322: E/AndroidRuntime(1700):     at android.os.Looper.loop(Looper.java:137)
12-24 10:19:54.322: E/AndroidRuntime(1700):     at android.app.ActivityThread.main(ActivityThread.java:4340)
12-24 10:19:54.322: E/AndroidRuntime(1700):     at java.lang.reflect.Method.invokeNative(Native Method)
12-24 10:19:54.322: E/AndroidRuntime(1700):     at java.lang.reflect.Method.invoke(Method.java:511)
12-24 10:19:54.322: E/AndroidRuntime(1700):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
12-24 10:19:54.322: E/AndroidRuntime(1700):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
12-24 10:19:54.322: E/AndroidRuntime(1700):     at dalvik.system.NativeStart.main(Native Method)

【问题讨论】:

您需要检查您的调试日志并发布异常堆栈跟踪。 看来yoiu正在ui线程上运行网络相关操作。怀疑NetworkOnMainThreadException。发布堆栈跟踪 那我该怎么办呢。让它工作? 使用ThreadAsyncTask 你能用那个重写这个并帮助我吗,因为我用过一次,整个应用程序没有响应,数据没有被解析 【参考方案1】:

把这个写在你的 onCreate 中

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();

StrictMode.setThreadPolicy(policy); 

对于 API 级别 >9

并且还使用异步任务来解析值

【讨论】:

不,不建议这样做。如果您正在测试,那么确定。所有与网络相关的操作都必须在后台线程中完成【参考方案2】:

你有

 JSONObject json = jParser.getJSONFromUrl(url);

JSONParser

 HttpResponse httpResponse = httpClient.execute(httpPost);

在 ui 线程上运行网络相关操作。

使用AsyncTaskThread

http://developer.android.com/reference/android/os/AsyncTask.html

 new TheTask().execute(params);  

然后

class TheTask extends AsyncTask<Void,Void,Void>

    protected void doInbackground(Void... params)
    
       // your http request
      return null;
    

您可以将 asynctask 设置为 Fragment 的内部类并在onPostExecute 中更新 ui

编辑:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) 
    View rootView = inflater.inflate(R.layout.fragment_qm, container, false);
    new TheTask().execute(url);
    return rootView;

然后

 class TheTask extends AsyncTask<String,String,String>

    @override
    protected String doInbackground(String... params)
    
        String _response =null;
        try 
        // defaultHttpClient
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost(params[0]);

        HttpResponse httpResponse = httpClient.execute(httpPost);
        HttpEntity httpEntity = httpResponse.getEntity();
         _response=EntityUtils.toString(httpEntity);
        catch(Exception e)
        
           e.printStacktrace();
         
      return _response;
    
    @Override
    protected void onPostExecute(String result) 
    // TODO Auto-generated method stub
    super.onPostExecute(result);
    Log.i(".......",result);




【讨论】:

谢谢。我会照你说的做,然后回到你身边。 我现在明白了 12-24 11:07:04.802: W/dalvikvm(1848): threadid=1: 线程以未捕获的异常退出 (group=0x409961f8) 12-24 11:07:04.822 : E/AndroidRuntime(1848): FATAL EXCEPTION: main 12-24 11:07:04.822: E/AndroidRuntime(1848): java.lang.NullPointerException: println 需要消息 12-24 11:07:04.822: E/AndroidRuntime (1848): 在 android.util.Log.println_native(Native Method) 12-24 11:07:04.822: E/AndroidRuntime(1848): 在 android.util.Log.i(Log.java:159) 12-24 11:07:04.822: E/AndroidRuntime(1848): 在 com.qrodsintegrated.QMFragment$TheTask.onPostExecute(QMFragment.java:122) 12-24 11:07:04.822: E/AndroidRuntime(1848): 在 com.qrodsintegrated.QMFragment$TheTask.onPostExecute(QMFragment.java:1) 12-24 11:07:04.822: E/AndroidRuntime(1848): 在 android.os.AsyncTask.finish(AsyncTask .java:602) 12-24 11:07:04.822: E/AndroidRuntime(1848): 在 android.os.AsyncTask.access$600(AsyncTask.java:156) 12-24 11:07:04.822: E/AndroidRuntime( 1848): 在 android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:615) @Ruch1234 发布一个包含相关细节的新问题。我相信您的问题可以解决 @Ruch1234 因为这篇文章已经有一个公认的答案,所以进一步编辑它是不好的。新问题发布新问题。如果不是我,还有很多有才华的人,你的问题很快就会得到解决

以上是关于在 Fragments 中使用 JSON 时,应用在 Android 开发中没有响应的主要内容,如果未能解决你的问题,请参考以下文章

我正在使用 Fragments,当我快速按下后退按钮时,应用程序崩溃了。它随机发生

将 ViewPager 与 Fragments 一起使用时,在滑动时会破坏 Fragment

使用 Fragments 和 ViewPager 一段时间后,Android 应用程序崩溃

在Fragments中保存和恢复ListView(livedata)

在Android中使用ActivityGroup或Fragments等正确管理导航?

使用 Fragments 为 Android 中的每个选项卡单独返回堆栈