Android Listview每行都有不同的布局Java NullPointerException

时间:2014-06-05 18:53:05

标签: java android listview

解决!看下面的编辑!

我正在尝试创建一个列表视图来显示不同类型的布局但是收到此错误

(当我向上滚动,向下滚动并看到两种类型的布局后,我收到此错误)

E/AndroidRuntime﹕ FATAL EXCEPTION: main
    java.lang.NullPointerException

我可以滚动到底部并查看两种类型的布局(当注释为“//这一个!”的else语句需要时,无法同时看到它们(错误)

我的适配器的代码如下 - (按照@ matiash的建议编辑)

    public class NewsAdapter extends ArrayAdapter<NewsXMLData> {

    ImageLoader imageLoader;
    DisplayImageOptions options;

    private static final int TYPE_ITEM = 0;
    private static final int TYPE_SEPARATOR = 1;
    private static final int TYPE_MAX_COUNT = TYPE_SEPARATOR + 1;

    private LayoutInflater mInflater;

    public NewsAdapter(Context ctx, int textViewResourceId, List<NewsXMLData> sites) {
        super(ctx, textViewResourceId, sites);




        //Setup the ImageLoader, we'll use this to display our images
        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(ctx).build();
        imageLoader = ImageLoader.getInstance();
        imageLoader.init(config);

        //Setup options for ImageLoader so it will handle caching for us.
        options = new DisplayImageOptions.Builder()
                .cacheInMemory()
                .cacheOnDisc()
                .build();


    }
    @Override
    public int getItemViewType(int position) {

       if(getItem(position).getType().equals("image")) {

            return TYPE_ITEM;

       }

       else{

            return TYPE_SEPARATOR;
       }
    }

    @Override
    public int getViewTypeCount() {
        return TYPE_MAX_COUNT;
    }
    public static class ViewHolder {
        public ImageView iconImg = null;
        public TextView contentTxt = null;
        public TextView imageTitleTxt = null ;
        public ProgressBar imageIndicator = null ;
        public TextView textTitleTxt = null ;
        public ProgressBar textIndicator = null;
    }




    String flag;
    //@Override
    public View getView(int pos, View convertView, ViewGroup parent){
        ViewHolder holder =null;
        int type = getItemViewType(pos);
        Log.i("APP", "getView " + pos + " " + convertView + " type = " + type);
        View row = convertView;

        mInflater = (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        try {

            if (null == row) {
                //No recycled View, we have to inflate one.
                holder = new ViewHolder();
                switch (type){
                    case TYPE_ITEM:
                        row = (RelativeLayout) mInflater.inflate(R.layout.row_news, null);

                        holder.iconImg = (ImageView) row.findViewById(R.id.newsImageView);
                        holder.imageTitleTxt = (TextView) row.findViewById(R.id.newsTitleText);
                        holder.imageIndicator = (ProgressBar) row.findViewById(R.id.newsProgressBar);
                        holder.iconImg.setVisibility(View.INVISIBLE);
                        holder.imageIndicator.setVisibility(View.VISIBLE);
                        holder.imageTitleTxt.setVisibility(View.INVISIBLE);
                        //Setup a listener we can use to swtich from the loading indicator to the Image once it's ready
                        ImageLoadingListener listener = new ImageLoadingListener() {


                            @Override
                            public void onLoadingStarted(String arg0, View arg1) {
                                // TODO Auto-generated method stub

                            }

                            @Override
                            public void onLoadingCancelled(String arg0, View arg1) {
                                // TODO Auto-generated method stub

                            }

                            @Override
                            public void onLoadingComplete(String arg0, View arg1, Bitmap arg2) {

                            }

                            @Override
                            public void onLoadingFailed(String arg0, View arg1, FailReason arg2) {
                                // TODO Auto-generated method stub
                            }

                        };
                        holder.iconImg.setVisibility(View.VISIBLE);
                        holder.imageIndicator.setVisibility(View.INVISIBLE);
                        holder.imageTitleTxt.setVisibility(View.VISIBLE);
                         //Load the image and use our options so caching is handled.
                        imageLoader.displayImage(getItem(pos).getImgUrl(), holder.iconImg, options, listener);
                        //Set the relavent text in our TextViews
                        holder.imageTitleTxt.setText(getItem(pos).getTitle());
                        break;
                    case TYPE_SEPARATOR:
                        row = (RelativeLayout) mInflater.inflate(R.layout.row_news_text, null);
                        holder.contentTxt = (TextView) row.findViewById(R.id.newsTextContentText);
                        holder.textTitleTxt = (TextView) row.findViewById(R.id.newsTextTitleText);
                        holder.textIndicator = (ProgressBar) row.findViewById(R.id.newsTextProgressBar);

                        /*holder.contentTxt.setVisibility(View.INVISIBLE);
                        holder.textIndicator.setVisibility(View.VISIBLE);
                        holder.textTitleTxt.setVisibility(View.INVISIBLE);*/


                        holder.contentTxt.setVisibility(View.VISIBLE);
                        holder.textIndicator.setVisibility(View.INVISIBLE);
                        holder.textTitleTxt.setVisibility(View.VISIBLE);
                        holder.textTitleTxt.setText(getItem(pos).getTitle());
                        holder.contentTxt.setText(getItem(pos).getContent());
                        break;
                }
                convertView.setTag(holder);
            }
            else{
                holder = (ViewHolder)convertView.getTag();

            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return row;


    }

}

有什么建议吗?

此外,除了解析XML并将内容显示为列表视图之外,还有更好的方法吗?

编辑:现在,感谢@Jens和@matiash,代码正常运行 代码:

public class NewsAdapter extends ArrayAdapter<NewsXMLData> {

    ImageLoader imageLoader;
    DisplayImageOptions options;

    private static final int TYPE_ITEM = 0;
    private static final int TYPE_SEPARATOR = 1;
    private static final int TYPE_MAX_COUNT = TYPE_SEPARATOR + 1;

    private LayoutInflater mInflater;

    public NewsAdapter(Context ctx, int textViewResourceId, List<NewsXMLData> sites) {
        super(ctx, textViewResourceId, sites);




        //Setup the ImageLoader, we'll use this to display our images
        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(ctx).build();
        imageLoader = ImageLoader.getInstance();
        imageLoader.init(config);

        //Setup options for ImageLoader so it will handle caching for us.
        options = new DisplayImageOptions.Builder()
                .cacheInMemory()
                .cacheOnDisc()
                .build();


    }
    @Override
    public int getItemViewType(int position) {

       if(getItem(position).getType().equals("image")) {

            return TYPE_ITEM;

       }

       else{

            return TYPE_SEPARATOR;
       }
    }

    @Override
    public int getViewTypeCount() {
        return TYPE_MAX_COUNT;
    }
    public static class ViewHolder {
        public ImageView iconImg = null;
        public TextView contentTxt = null;
        public TextView imageTitleTxt = null ;
        public ProgressBar imageIndicator = null ;
        public TextView textTitleTxt = null ;
        public ProgressBar textIndicator = null;
    }




    String flag;
    //@Override
    public View getView(int pos, View convertView, ViewGroup parent){
        ViewHolder holder =null;
        int type = getItemViewType(pos);
        //Log.i("APP", "getView " + pos + " " + convertView + " type = " + type);
        View row = convertView;

        mInflater = (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        try {

            if (null == row) {
                //No recycled View, we have to inflate one.
                holder = new ViewHolder();
                switch (type) {
                    case TYPE_ITEM:
                        row = (RelativeLayout) mInflater.inflate(R.layout.row_news, null);


                        break;
                    case TYPE_SEPARATOR:
                        row = (RelativeLayout) mInflater.inflate(R.layout.row_news_text, null);

                        break;
                }
                //Log.i("APP","holder" + holder);
            }
                if(type==TYPE_ITEM){
                holder = new ViewHolder();
                holder.iconImg = (ImageView) row.findViewById(R.id.newsImageView);
                holder.imageTitleTxt = (TextView) row.findViewById(R.id.newsTitleText);
                holder.imageIndicator = (ProgressBar) row.findViewById(R.id.newsProgressBar);
                holder.iconImg.setVisibility(View.INVISIBLE);
                holder.imageIndicator.setVisibility(View.VISIBLE);
                holder.imageTitleTxt.setVisibility(View.INVISIBLE);
                //Setup a listener we can use to swtich from the loading indicator to the Image once it's ready
                ImageLoadingListener listener = new ImageLoadingListener() {


                    @Override
                    public void onLoadingStarted(String arg0, View arg1) {
                        // TODO Auto-generated method stub

                    }

                    @Override
                    public void onLoadingCancelled(String arg0, View arg1) {
                        // TODO Auto-generated method stub

                    }

                    @Override
                    public void onLoadingComplete(String arg0, View arg1, Bitmap arg2) {

                    }

                    @Override
                    public void onLoadingFailed(String arg0, View arg1, FailReason arg2) {
                        // TODO Auto-generated method stub
                    }

                };
                holder.iconImg.setVisibility(View.VISIBLE);
                holder.imageIndicator.setVisibility(View.INVISIBLE);
                holder.imageTitleTxt.setVisibility(View.VISIBLE);
                //Load the image and use our options so caching is handled.
                imageLoader.displayImage(getItem(pos).getImgUrl(), holder.iconImg, options, listener);
                //Set the relavent text in our TextViews
                holder.imageTitleTxt.setText(getItem(pos).getTitle());
            }
            else if(type==TYPE_SEPARATOR){
                holder = new ViewHolder();
                holder.contentTxt = (TextView) row.findViewById(R.id.newsTextContentText);
                holder.textTitleTxt = (TextView) row.findViewById(R.id.newsTextTitleText);
                holder.textIndicator = (ProgressBar) row.findViewById(R.id.newsTextProgressBar);

                        /*holder.contentTxt.setVisibility(View.INVISIBLE);
                        holder.textIndicator.setVisibility(View.VISIBLE);
                        holder.textTitleTxt.setVisibility(View.INVISIBLE);*/


                holder.contentTxt.setVisibility(View.VISIBLE);
                holder.textIndicator.setVisibility(View.INVISIBLE);
                holder.textTitleTxt.setVisibility(View.VISIBLE);
                holder.textTitleTxt.setText(getItem(pos).getTitle());
                holder.contentTxt.setText(getItem(pos).getContent());
            }
        }
        catch(Exception e){
            e.printStackTrace();

        }
        return row;


    }

}

2 个答案:

答案 0 :(得分:0)

首先,if (type=="image")flag != type不是比较Java中的字符串的正确方法。见How do I compare strings in Java?。这意味着您的代码将无法完成您的预期,使用不正确的ifs一直向下

其次,对于像这样的ListView,使用“混合”项目视图,有一个更优雅(和内置)的解决方案。通过实现getViewTypeCount()(返回2)和getItemViewType()(返回每个项目的类型),框架可以为不同的视图类型保留不同的回收列表。

这意味着您可以相信,当您传递非空convertView时,它将是您为相同项目类型充气的那个(并且您可以完全取消flag!=type检查)

答案 1 :(得分:0)

Holder为空。你能用调试器来检查吗?删除com.justduthings.companion.NewsAdapter中的第172行。