草庐IT

android - 如何在 android 中从 json 动态创建可扩展 ListView 中的组和子项?

coder 2023-11-27 原文

我正在 Android 中开发客户端-服务器项目。我需要从给定的 URL 解析 JSON 并将其放在 ExpandableListView 中。在 JSON 响应中,我正在获取包含数组的节点的数据。因此,我必须将主要的 JsonArray 放置到 ExpandableListView 中的组中。它工作正常。

我可以从 JSON 中找出有多少组,但是当我试图根据来自服务器的数据将 child 放入每个组时,问题就出现了。我的代码只将第一个 child 放在第一组中,但是当我点击第二个 child 时,它显示错误。

我需要将“ID”和“用户名”放在相应的组中(例如:电子邮件、传真、上传)。我的代码可以将一个 child 的信息放在一组中,但是当我单击第二组时,它崩溃了。我们将不胜感激任何形式的帮助。

那么,我的问题是,如何根据服务器数据动态创建组并将子数据放入每个子项中?

这是日志中的错误:

04-07 17:49:02.194: E/AndroidRuntime(13285): FATAL EXCEPTION: main
04-07 17:49:02.194: E/AndroidRuntime(13285): java.lang.IndexOutOfBoundsException: Invalid index 1, size is 1
04-07 17:49:02.194: E/AndroidRuntime(13285):    at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:251)
04-07 17:49:02.194: E/AndroidRuntime(13285):    at java.util.ArrayList.get(ArrayList.java:304)
04-07 17:49:02.194: E/AndroidRuntime(13285):    at android.widget.SimpleExpandableListAdapter.getChildrenCount(SimpleExpandableListAdapter.java:255)
04-07 17:49:02.194: E/AndroidRuntime(13285):    at android.widget.ExpandableListConnector.refreshExpGroupMetadataList(ExpandableListConnector.java:561)
04-07 17:49:02.194: E/AndroidRuntime(13285):    at android.widget.ExpandableListConnector.expandGroup(ExpandableListConnector.java:682)
04-07 17:49:02.194: E/AndroidRuntime(13285):    at android.widget.ExpandableListView.handleItemClick(ExpandableListView.java:561)
04-07 17:49:02.194: E/AndroidRuntime(13285):    at android.widget.ExpandableListView.performItemClick(ExpandableListView.java:521)
04-07 17:49:02.194: E/AndroidRuntime(13285):    at android.widget.AbsListView$PerformClick.run(AbsListView.java:2514)
04-07 17:49:02.194: E/AndroidRuntime(13285):    at android.widget.AbsListView$1.run(AbsListView.java:3168)
04-07 17:49:02.194: E/AndroidRuntime(13285):    at android.os.Handler.handleCallback(Handler.java:605)
04-07 17:49:02.194: E/AndroidRuntime(13285):    at android.os.Handler.dispatchMessage(Handler.java:92)
04-07 17:49:02.194: E/AndroidRuntime(13285):    at android.os.Looper.loop(Looper.java:137)
04-07 17:49:02.194: E/AndroidRuntime(13285):    at android.app.ActivityThread.main(ActivityThread.java:4424)
04-07 17:49:02.194: E/AndroidRuntime(13285):    at java.lang.reflect.Method.invokeNative(Native Method)
04-07 17:49:02.194: E/AndroidRuntime(13285):    at java.lang.reflect.Method.invoke(Method.java:511)

JSON 响应

{   "email":[   
    {"ID":"123","username":"dipakadmin"},
    {"ID":"3233","username":"raju"},
    {"ID":"5445","username":"hussain"}
    ]
,
"fax":[ 
    {"ID":"6665","username":"mohammad"},
    {"ID":"9877","username":"raj"},
    {"ID":"87655","username":"aryan"}
    ]
,
"upload":
    [   
    {"ID":"132322","username":"raja"},
    {"ID":"544333","username":"bala"},
    ]
}

这只是一个 JSON 响应的例子。真实的回复有很多标签。

ExpandableListActivity 的代码示例如下:

package com.ExpandableListActivity;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.ExpandableListActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.SimpleExpandableListAdapter;
import android.widget.TextView;

public class DocumentCenter extends ExpandableListActivity {

    public static JSONObject  jsonDocu=null;
    JSONArray jArray = null;
    JSONObject json_data = null;
    JSONObject root = null;

    List<List<Map<String, String>>> childs;

    List<Map<String, String>> child1;
    List<Map<String, String>> child2;
    List<Map<String, String>> child3;
    SimpleExpandableListAdapter adapter;

    Map<String, String> childdata1;

    public static String url3=null;
    String strEmailNull=null;
    String strFaxNull=null;
    String strUploadNull=null;
    public String user=null;
    TextView txtMLSID;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main2);

        user= TabBarExample.getJsonUser;
        Log.e("log_tag","USERNAME On Document : "+user); 

        List<Map<String, String>> groups = new ArrayList<Map<String, String>>();

        child1 = new ArrayList<Map<String, String>>();
        child2 = new ArrayList<Map<String, String>>();
        child3 = new ArrayList<Map<String, String>>();  

        url3 ="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
        Log.e("log_tag","URL on DOCUMENT : "+url3); 
        try {
            jsonDocu = JSONfunctions1.getJSONfromURL(url3);
            JSONArray ary = jsonDocu.names();

            Log.e("log_tag","ary : "+ary .toString()); 

            for (int i1 = 0; i1 < ary.length(); i1++) {
                String value =      ary.get(i1).toString();
                Log.e("log_tag","value : "+value); 
                strEmailNull=   jsonDocu.getString(value);
                if (!strEmailNull.equals("null")){
                    try{
                        Map<String, String> group1 = new HashMap<String, String>();
                        group1.put("group", value);
                        //group1.put("group", value+(i1+1));
                        groups.add(group1);

                        JSONArray  email = jsonDocu.getJSONArray(value);
                        for(int i=0;i<email.length() ;i++){                     
                            childdata1 = new HashMap<String, String>();

                            JSONObject e = email.getJSONObject(i+1);
                            childdata1.put("child", e.getString("ID"));
                            childdata1.put("child1",  "Name:  "+e.getString("name"));
                            childdata1.put("child2", "Size:  "+e.getString("size"));
                            childdata1.put("child3",  "Update:  "+e.getString("lastUpdate"));

                            child1.add(childdata1); 
                            childs = new ArrayList<List<Map<String, String>>>();
                        }
                    }catch(JSONException e){
                        Log.e("log_tag", "Error parsing data "+e.toString());
                    }
                }
            }
            childs.add(child1);
        } catch (JSONException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        adapter = new SimpleExpandableListAdapter(
            this, groups, R.layout.groups2, new String[] { "group" },
            new int[] { R.id.group }, childs, R.layout.childs2,
            new String[] { "child1","child2" ,"child3"}, new int[] { R.id.child1, R.id.child2, R.id.child3});
        setListAdapter(adapter);
    }

    @Override
    public boolean setSelectedChild(int groupPosition, int childPosition,
        boolean shouldExpandGroup) {
        //do something
        Log.e("log_tag","setSelectedChild: "); 
        return super.setSelectedChild(groupPosition, childPosition,
            shouldExpandGroup);
    }

    @Override
    public void setSelectedGroup(int groupPosition) {
        //do something

        Log.e("log_tag","setSelectedGroup: "); 
        super.setSelectedGroup(groupPosition);
    }
}

最佳答案

下面是我的做法。当然,您可以像解析一样使用解析。但是,我会使用 jackson 库并根据响应创建一个对象类,并使用 ObjectMapper,它看起来更优雅并且可以节省您的解析时间。您可以根据需要在此处添加更多字段,例如内部传真和电子邮件类和列表:

public class ResponseObject {

private List<Email> email;

/**
 * @return the email
 */
public List<Email> getEmail() {
    return email;
}

/**
 * @param email
 *            the email to set
 */
public void setEmail(List<Email> email) {
    this.email = email;
}

public static class Email {
    private Integer ID;
    private String username;

    /**
     * @return the ID
     */
    public Integer getID() {
        return ID;
    }

    /**
     * @param ID
     *            the ID to set
     */
    public void setID(Integer ID) {
        ID = ID;
    }

    /**
     * @return the username
     */
    public String getUsername() {
        return username;
    }

    /**
     * @param username
     *            the username to set
     */
    public void setUsername(String username) {
        this.username = username;
    }
}
}

然后像这样使用 BaseExpandableListAdapter,根据需要进行更改和添加 View :

import java.util.ArrayList;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseExpandableListAdapter;

public class ResponseAdapter extends BaseExpandableListAdapter {
private ArrayList<ResponseObject> responseList = new ArrayList<ResponseObject>();

public ResponseAdapter(ArrayList<ResponseObject> responseObject) {
    this.responseList = responseObject;
}

@Override
public Object getChild(int groupPosition, int childPosition) {
    // TODO Auto-generated method stub
    return null;
}

@Override
public long getChildId(int groupPosition, int childPosition) {
    // TODO Auto-generated method stub
    return 0;
}

@Override
public View getChildView(int groupPosition, int childPosition,
        boolean isLastChild, View convertView, ViewGroup parent) {
    int ID = responseList.get(groupPosition).getEmail().get(childPosition)
            .getID();
    String username = responseList.get(groupPosition).getEmail()
            .get(childPosition).getUsername();
    return null;
}

@Override
public int getChildrenCount(int groupPosition) {
    return responseList.get(groupPosition).getEmail().size();
}

@Override
public Object getGroup(int groupPosition) {
    // TODO Auto-generated method stub
    return null;
}

@Override
public int getGroupCount() {
    return responseList.size();
}

@Override
public long getGroupId(int groupPosition) {
    // TODO Auto-generated method stub
    return 0;
}

@Override
public View getGroupView(int groupPosition, boolean isExpanded,
        View parent, ViewGroup viewGroup) {
    // Email group goes here
    return null;
}

@Override
public boolean hasStableIds() {
    // TODO Auto-generated method stub
    return false;
}

@Override
public boolean isChildSelectable(int arg0, int arg1) {
    // TODO Auto-generated method stub
    return false;
}

}

关于android - 如何在 android 中从 json 动态创建可扩展 ListView 中的组和子项?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10054711/

有关android - 如何在 android 中从 json 动态创建可扩展 ListView 中的组和子项?的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  3. ruby - 如何在 Ruby 中顺序创建 PI - 2

    出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits

  4. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  5. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  6. ruby-on-rails - Rails 3 中的多个路由文件 - 2

    Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

  7. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  8. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  9. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  10. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

随机推荐