【问题标题】:Parse Data from XML into List with Custom Adapter使用自定义适配器将 XML 中的数据解析为列表
【发布时间】:2017-02-19 16:49:18
【问题描述】:

我正在从网站上传的 XML 中获取数据。我想在自定义ListView 中显示来自 XML 的文本,它有两个TextViews。 'title' 应该进入上层TextView,'guid' 进入下层TextView。我不知道我应该怎么做。我编写了以下自定义适配器。

CustomAdapter.java

public class CustomAdapter extends BaseAdapter {

    private ArrayList list;
    private LayoutInflater layoutInflater;

    public CustomAdapter(Context context, ArrayList list) {
        this.list= list;
        layoutInflater = LayoutInflater.from(context);
    }

    @Override
    public int getCount() {
        return list.size();
    }

    @Override
    public Object getItem(int position) {
        return list.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        final ViewHolder holder;
        if (convertView == null) {

            convertView = layoutInflater.inflate(R.layout.layout_list_row, null);

            holder = new ViewHolder();
            holder.backgroundImage = (ImageView) convertView.findViewById(R.id.backgroundImage);
            holder.topText = (TextView) convertView.findViewById(R.id.topText);
            holder.bottomText = (TextView) convertView.findViewById(R.id.bottomText);
            convertView.setTag(holder);

        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        DiscourseItem discourseItem = (DiscourseItem) discourseList.get(position);
        holder.topText.setText(discourseItem.getTopText());
        holder.bottomText.setText(discourseItem.getBottomText());

        return convertView;
    }

    static class ViewHolder {
        ImageView backgroundImage;
        TextView topText;  //This should display the text in the 'title' field
        TextView bottomText; //This should display the text in the 'guid' field
    }

}

我目前能够在单独的ListViews 和正常的ArrayAdapters 中分别显示这两个。这是我写的代码。

XMLParser.java

public class XMLParser extends AsyncTask {

    private URL url;
    public ArrayList<String> title = new ArrayList<>();
    public ArrayList<String> guid = new ArrayList<>();

    @Override
    protected Object doInBackground(Object[] objects) {
        try {
            url = new URL(removed);

            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
            factory.setNamespaceAware(false);
            XmlPullParser xpp = factory.newPullParser();

            xpp.setInput(getInputStream(url), null);

            boolean insideItem = false;

            int eventType = xpp.getEventType();
            while (eventType != XmlPullParser.END_DOCUMENT) {
                if (eventType == XmlPullParser.START_TAG) {
                    if (xpp.getName().equalsIgnoreCase("item")){
                        insideItem = true;
                    } else if (xpp.getName().equalsIgnoreCase("title")){
                        if (insideItem)
                            title.add(xpp.nextText());
                    } else if (xpp.getName().equalsIgnoreCase("guid")){
                        if (insideItem)
                            guid.add(xpp.nextText());
                    }
                } else if (eventType == XmlPullParser.END_TAG && xpp.getName().equalsIgnoreCase("item")){
                    insideItem = false;
                }
                eventType = xpp.next();
            }
        } catch (MalformedURLException e){
            e.printStackTrace();
        } catch (XmlPullParserException e){
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return title;
    }

    public InputStream getInputStream(URL url){
        try {
            return url.openConnection().getInputStream();
        } catch (IOException e){
            e.printStackTrace();
        }
        return null;
    }

    public ArrayList<String> titles(){
        return title;
    }

    public ArrayList<String> guids(){
        return guid;
    }
}

MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        parser = new XMLParser();
        parser.execute();
        title = parser.titles();
        guid = parser.guids();

        final Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
           @Override
            public void run() {
                discourseList = getDiscourseList();
            }
            }, 2000);
        }
        });

        ListView listView = (ListView) findViewById(R.id.discourseList);
        listView.setAdapter(new CustomAdapter(this, discourseList));
    }

    private ArrayList<DiscourseItem> getDiscourseList() {
        ArrayList<DiscourseItem> listData = new ArrayList<DiscourseItem>();
        String[] topText = new String[title.size()];
        topText = title.toArray(topText);

        String[] bottomText = new String[guid.size()];
        bottomText = guid.toArray(bottomText);

        for (int i = 0; i <= title.size(); i++) {
            try {
                DiscourseItem discourseItem = new DiscourseItem();
                discourseItem.setTopText(topText[i]);
                discourseItem.setBottomText(bottomText[i]);
                listData.add(discourseItem);
            } catch (ArrayIndexOutOfBoundsException e){
                e.printStackTrace();
            }
        }
        return listData;
    }
}

编辑:

我已经进行了上述更改。现在,当解析器运行并调用getDiscourseList() 时,它会在discourseItem.setTopText(topText[i]); 处引发以下错误:

java.lang.ArrayIndexOutOfBoundsException: length=2; index=2

【问题讨论】:

    标签: java android arrays listview xml-parsing


    【解决方案1】:

    您可以为您的上限和下限创建包装类(类似这样,考虑另一个名称,因为我不知道您的数据的上下文):

    public class TitleGuidPair {
      private final String title;
      private final String guid;
      public TitleGuidPair(String title, String guid) {
        this.title = title;
        this.guid = guid;
      }
     //getters
    }
    

    然后将结果解析为 TitleGuidPair 的 ArrayList。如果您想保留您的解析算法,您可以进行一些后期处理,然后从您拥有的两个列表中构建您的 TitleGuidPairs。

    将这一步传递给您的适配器 List of TitleGuidPairs 并在 getView 方法中设置顶部和底部文本,如

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
    
        final ViewHolder holder;
        if (convertView == null) {
    
            convertView = layoutInflater.inflate(R.layout.layout_list_row, null);
    
            holder = new ViewHolder();
            holder.backgroundImage = (ImageView) convertView.findViewById(R.id.backgroundImage);
            holder.topText = (TextView) convertView.findViewById(R.id.topText);
            holder.bottomText = (TextView)    convertView.findViewById(R.id.bottomText);
            TitleGuidPair titleGuidPair = list.get(position);  
            holder.topText.setText(titleGuidPair.getTitle());
            holder.bottomText.setText(titleGuidPair.getGuid());
            convertView.setTag(holder);
    
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        return convertView;
    }
    

    【讨论】:

    • 所以,我进行了更改以使用ListView 来显示数据,但它会抛出ArrayIndexOutOfBoundsException。我已经更新了 OP 以反映代码和错误。
    • 您声明数组的大小是 title.size()。因此,您可以访问从 0 到大小 -1 的索引。在您的循环中,您正在从 0 到大小的索引闪烁。请将您的循环从 for (int i = 0; i
    • 好的,非常感谢。就在我在这里发布这个之后,我再次浏览了我的代码并注意到了这一点。是的,每个标题都有一个指南,所以这不会成为问题。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 2020-02-02
    • 1970-01-01
    • 2016-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多