0

你好,我很难理解如何用我的 JSON 解析器做我想做的事。我目前正在解析位于http://api.pathofexile.com/leagues?type=all的数据以提取联赛 ID(目前它们是“默认”、“硬核”、“2 月 12 日 Solo HC Race”,等)我的解析器当前将这些 id 放入列表视图中。

我遇到的问题是这些 id 会随着时间而改变。他们也有自己的 JSON url,我需要根据联赛 id 对其进行解析。例如,如果联赛 id 是“默认”,我需要获取该 id 并将其放入 url:

"api.pathofexile.com/leagues/"+ id +"?ladder=1&ladderOffset=1&ladderLimit=2" 获取http://api.pathofexile.com/leagues/Default?ladder=1&ladderOffset=1&ladderLimit=2

基本上,我希望能够单击列表视图中的 id 并让它更新 url 并将新数据解析到单独的列表中。

这是我的 JSON 解析器:

public class Leagues extends ListActivity {
    public static String url = "http://api.pathofexile.com/leagues?type=all";

    private static final String TAG_ID = "id";
    static InputStream is = null;
    static JSONObject jObj = null;
    static String json = "";

    JSONArray leagues = null;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.list_item);
        new GetJSONTask().execute("");
    }

    protected class GetJSONTask extends AsyncTask<String, Integer, ArrayList<HashMap<String, String>>> {
        protected ArrayList<HashMap<String, String>> leaguesList;

        private final ProgressDialog dialog = new ProgressDialog(Leagues.this);

        // onPreExecute method
        protected void onPreExecute() {
            this.dialog.setMessage("Loading, Please Wait..");
            this.dialog.setCancelable(false);
            this.dialog.show();
        }

        // doInBackground method
        @Override
        protected ArrayList<HashMap<String, String>> doInBackground(String... params) {
            leaguesList = new ArrayList<HashMap<String, String>>();

            // defaultHttpClient
            try {
                DefaultHttpClient httpClient = new DefaultHttpClient();
                HttpGet HttpGet = new HttpGet(url);

                HttpResponse httpResponse = httpClient.execute(HttpGet);
                json = EntityUtils.toString(httpResponse.getEntity());

                // getting array of entries
                JSONArray leagues = new JSONArray(json);

                // looping through entries
                for (int i = 0; i < leagues.length(); i++) {
                    JSONObject league = leagues.getJSONObject(i);

                    String id = league.getString(TAG_ID);

                    // 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_EVENT, event);

                    // adding HashList to ArrayList
                    leaguesList.add(map);
                }
            } catch (JSONException e) {
                e.printStackTrace();
            } catch (ClientProtocolException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

            return leaguesList;
        }

        // onPostExecute method
        protected void onPostExecute(ArrayList<HashMap<String, String>> result) {
            ListAdapter adapter = new SimpleAdapter(getApplicationContext(), leaguesList, R.layout.league, new String[] { TAG_ID }, new int[] { R.id.id });
            // selecting single ListView item
            ListView lv = getListView();
            lv.setAdapter(adapter);

            if (this.dialog.isShowing()) {
                this.dialog.dismiss();
            }

        }
    }

}

在这一点上我很迷茫。我现在尝试设置解析器的方式是否可行?谁能指出我正确的方向?

谢谢。

编辑进一步澄清:

现在我的解析器会将联赛 id 从 url "api.pathofexile.com/leagues?type=all" 放入 ListView 中,如下所示:

  1. 默认
  2. 铁杆
  3. 2 月 12 日个人 HC 比赛

(这些项目会随着时间而改变)

我希望能够单击“默认”,这会将 url 更改为“api.pathofexile.com/leagues/Default?ladder=1&ladderOffset=1&ladderLimit=2”并将其解析为新的 ListView。

更新: 使用 Darwind 提供的项目,我改变了它(使用我的一些其他代码)以在单击联赛 ID 后显示我想要的 JSON 数据。

public class LeagueView extends ListActivity {
    //private TextView leagueId, leagueDescription;
    private static final String TAG_LADDER = "ladder";
    private static final String TAG_ENTRIES = "entries";
    private static final String TAG_ONLINE = "online";
    private static final String TAG_RANK = "rank";
    private static final String TAG_CHARACTER = "character";
    private static final String TAG_CHARNAME = "name";
    private static final String TAG_LEVEL = "level";
    private static final String TAG_CLASS = "class";
    private static final String TAG_EXPERIENCE = "experience";
    private static final String TAG_ACCOUNT = "account";
    private static final String TAG_ACCNAME = "name";
    private static final String TAG_ACCNAME2 = "name2";

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //setContentView(R.layout.league_layout);

    //leagueId = (TextView) findViewById(R.id.leagueId);
    //leagueDescription = (TextView) findViewById(R.id.leagueDescription);

    String urlToJson = getIntent().getExtras().getString("leagueUrl");

    if (urlToJson == null) {
        Toast.makeText(this, "Url was null!", Toast.LENGTH_LONG).show();
    } else {
        new LeagueTask().execute(urlToJson.replaceAll(" ", "%20"));
    }
}

protected class LeagueTask extends AsyncTask<String, Integer, League> {
    private final ProgressDialog dialog = new ProgressDialog(LeagueView.this);
    protected ArrayList<HashMap<String, String>> entriesList;

    // onPreExecute method
    protected void onPreExecute() {
        this.dialog.setMessage("Retrieving Ladder Information...");
        this.dialog.setCancelable(false);
        this.dialog.show();
    }

    // doInBackground method
    @Override
    protected League doInBackground(String... params) {
        League aLeague = new League();
        entriesList = new ArrayList<HashMap<String, String>>();

        // defaultHttpClient
        try {
            DefaultHttpClient httpClient = new DefaultHttpClient();
            HttpGet HttpGet = new HttpGet(params[0]);

            HttpResponse httpResponse = httpClient.execute(HttpGet);
            String json = EntityUtils.toString(httpResponse.getEntity());

            // Getting a JSONObject filled.
            JSONObject leagueObject = new JSONObject(json);

            //String id = leagueObject.getString("id");
            //String description = leagueObject.getString("description");

            JSONObject ladder = leagueObject.getJSONObject(TAG_LADDER);
            JSONArray entries = ladder.getJSONArray(TAG_ENTRIES);

            // looping through entries
            for (int i = 0; i < entries.length(); i++) {
                JSONObject ent = entries.getJSONObject(i);

                // storing each JSON item in a variable
                String online = ent.getString(TAG_ONLINE);
                if (online == "false")
                    online = "Offline";
                else online = "Online";
                String rank = ent.getString(TAG_RANK);

                // pull out character object
                JSONObject character = ent.getJSONObject(TAG_CHARACTER);
                String chName = character.getString(TAG_CHARNAME);
                String lvl = character.getString(TAG_LEVEL);
                String cl = character.getString(TAG_CLASS);
                String xp = character.getString(TAG_EXPERIENCE);

                // pull out account object
                JSONObject account = ent.getJSONObject(TAG_ACCOUNT);
                String accName = account.getString(TAG_ACCNAME);

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

                // adding each child node to HashMap key => value
                map.put(TAG_ONLINE, online);
                map.put(TAG_CHARNAME, chName);
                map.put(TAG_ACCNAME2, accName);
                map.put(TAG_RANK, rank);
                map.put(TAG_LEVEL, lvl);
                map.put(TAG_EXPERIENCE, xp);
                map.put(TAG_CLASS, cl);

                entriesList.add(map);
            }

            // creating a league to display
            aLeague = new League();
            //aLeague.setLeagueId(id);
            //aLeague.setDescription(description);

        } catch (JSONException e) {
            e.printStackTrace();
        } catch (ClientProtocolException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return aLeague;
    }

    // onPostExecute method
    protected void onPostExecute(League result) {
        //leagueId.setText(result.getLeagueId());
        //leagueDescription.setText(result.getDescription());

        ListAdapter adapter = new SimpleAdapter(getApplicationContext(), entriesList, R.layout.league_layout, new String[] { TAG_RANK, TAG_CHARNAME, TAG_LEVEL, TAG_EXPERIENCE, TAG_CLASS }, new int[] { R.id.rank, R.id.chName, R.id.lvl, R.id.experience, R.id.cl });
        // selecting single ListView item
        ListView lv = getListView();
        lv.setAdapter(adapter);

        if (this.dialog.isShowing()) {
            this.dialog.dismiss();
        }
    }
}
}
4

3 回答 3

0

我建议不要自己编写解析器,而是使用 JSON 开发的解析器
http://json.org/java/

于 2013-02-11T22:49:31.933 回答
0

乔菲斯,我正在编辑我的答案。

所以我模拟了你的代码并在本地运行它。现在我明白你在做什么了。你的问题有两个部分。我认为问题描述名称不正确,您的描述似乎集中在可点击的列表视图项上,但您的摘要似乎围绕解析 json。

另请注意,http://api.pathofexile.com/leagues/Hardcore? ladder=1&ladderOffset=1&ladderLimit=2 未提供格式正确的 json 文本,缺少开头和结尾的方括号。这是不正确的,它返回的是单个 JSONObject 而不是数组

第一部分:使列表视图项目可点击,使用 ListView.setOnItemClickListener 使项目可点击。例如看这个教程:http ://www.ezzylearning.com/tutorial.aspx?tid=1351248

第二部分点击时会发生什么。其中一部分将用于 setOnItemClickListener 的实现,第二部分是构建新链接并单击它并返回内容的 JSON。您正在返回 ArrayList<HashMap<String, String>> LeaguesList; 这似乎非常有限,您为什么不返回 JSONArray 本身或 ArrayList<HashMap<String,JSONObject>> ,其中地图以 ID 作为键,并且 JSONObject 中的所有元素都可以稍后使用,除非 ID 是您唯一的东西有兴趣?

我手边没有 android 模拟器,但如果您需要有关 JSON 解析器的任何帮助,请告诉我。

这就是我想象的工作方式,onclick 事件将从

        public static String PATTERN =
          "http://api.pathofexile.com/leagues/" + ID_TOKEN +
          "?ladder=1&ladderOffset=1&ladderLimit=2";

使用传入的 Url 编码 ID,例如 Default,Feb 15 Solo HC Race,并将调用 GetJSONTask.doInBackGround 任务以获取新的 JSON 数组。

于 2013-02-12T00:03:08.403 回答
0

好的,基本上正如 vsnyc 指出的那样,您的标题可能有点误导。

我的看法是这样的:

  1. 通过解析 JSON 数组获取所有联赛的列表
  2. 通过解析 JSON 对象,可以单击列表中的联赛并获取提供有关所选联赛信息的视图。

我基本上去把你所有的代码都删了,并做了一些修改。例如我在评论中提到,你应该使用一个类来代表每个联赛,然后重写toString这种新对象的方法,这样这个类就可以直接在你的ListView.

作为您使用的第一个 url:http://api.pathofexile.com/leagues?type=all返回的是 JSON 数组而不是单个对象,并且此数组中的对象与选择特定联赛时返回的数据不同,我不建议使用相同的 AsyncTask 来获取两者联赛列表和单个联赛。

相反,在您ListView使用联赛填充第一个视图后,我将创建第二个视图,该视图通过从特定联赛获取数据来填充。

要获得代表一个联赛的第二个视图,您需要实现第一个视图的OnItemClickListenerfor ListView。在其中,OnItemClickListener您将获得选定的联赛名称并将其传递给下一个视图,该视图又将联系服务器并获取JSON表示给定联赛的对象并解析数据。

我创建了一个小项目,因为要添加到答案中的代码相当多,而且我需要更多的时间来删除所有不必要的代码,而不仅仅是给你一个完整的工作项目。;-)

这是 zip 文件中的项目:

https://dl.dropbox.com/u/27724371/AndroidListViews.zip

如果这不是您要找的,请告诉我。

于 2013-02-12T19:17:19.313 回答