Android BaseAdapter的getCount()getView()

时间:2014-10-26 11:49:29

标签: android listview gridview baseadapter

我有一个BaseAdapter,有3种布局,用于将JSONObject放到我的ListView中。适配器getCount()返回应该在ListView上显示的正确项目数,但它只显示第一个项目。

我试图在这里找到对此问题的另一个回应,但我没有找到。

这是我的代码:

public class PerfilInfoAdapter extends BaseAdapter {

    public static final int VIEW_TYPE_TITULO = 0;
    public static final int VIEW_TYPE_DESCRICAO = 1;
    public static final int VIEW_TYPE_KEY_VALUE = 2;

    private JSONArray list;
    private Activity activity;
    private ViewHolder viewHolder;

    public PerfilInfoAdapter(Activity activity, JSONArray list) {
        this.activity = activity;
        this.list = list;
    }

    protected class ViewHolder {
        TextView textViewTitulo;
        TextView textViewDescricao;
        TextView textViewKey;
        TextView textViewValue;
    }

    @Override
    public int getCount() {
        Log.d("PerfilInfoAdapter", "Number of items in array: " + Integer.toString(this.list.length()));
        return this.list.length();
    }

    @Override
    public JSONObject getItem(int position) {
        JSONObject json = null;

        try {
            json = this.list.getJSONObject(position);
        } catch (JSONException e) {
            e.printStackTrace();
        }

        return json;
    }

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

    @Override
    public int getItemViewType(int position) {

        int retorno = -1;

        JSONObject json = null;

        try {
            json = this.list.getJSONObject(position);

            if (json.getString("key").equals("Titulo")) {
                retorno = VIEW_TYPE_TITULO;
            } else if (json.getString("key").equals("Descrição")
                    || json.getString("key").equals("Sou")) {
                retorno = VIEW_TYPE_DESCRICAO;
            } else {
                retorno = VIEW_TYPE_KEY_VALUE;
            }

        } catch (JSONException e) {
            e.printStackTrace();
        }

        return retorno;
    }

    @Override
    public int getViewTypeCount() {
        return 3;
    }

    @Override
    public View getView(int position, View container, ViewGroup viewGroup) {
        System.out.println("getView " + position + " " + container);

        this.viewHolder = null;

        int type = this.getItemViewType(position);

        if (container == null) {
            this.viewHolder = new ViewHolder();

            switch (type) {
            case VIEW_TYPE_TITULO:
                container = this.activity.getLayoutInflater().inflate(
                        R.layout.perfil_info_full_titulo, viewGroup, false);

                this.viewHolder.textViewTitulo = (TextView) container
                        .findViewById(R.id.perfil_info_full_textViewTitulo);
                break;
            case VIEW_TYPE_DESCRICAO:
                container = this.activity.getLayoutInflater().inflate(
                        R.layout.perfil_info_full_descricao, viewGroup, false);

                this.viewHolder.textViewDescricao = (TextView) container
                        .findViewById(R.id.perfil_info_full_textVewDescricao);
                break;
            case VIEW_TYPE_KEY_VALUE:
                container = this.activity.getLayoutInflater().inflate(
                        R.layout.perfil_info_list, viewGroup, false);

                this.viewHolder.textViewKey = (TextView) container
                        .findViewById(R.id.perfil_info_full_chave_valor_textFieldChave);
                this.viewHolder.textViewValue = (TextView) container
                        .findViewById(R.id.perfil_info_full_chave_valor_textFieldValor);
                break;
            }

            container.setTag(this.viewHolder);

        } else {
            this.viewHolder = (ViewHolder)container.getTag();
        }

        try {
            JSONObject json = this.list.getJSONObject(position);

            switch (type) {
            case VIEW_TYPE_TITULO:
                this.viewHolder.textViewTitulo.setText(json.getString("value"));
                break;
            case VIEW_TYPE_DESCRICAO:
                this.viewHolder.textViewDescricao.setText(json
                        .getString("value"));
                break;
            case VIEW_TYPE_KEY_VALUE:
                this.viewHolder.textViewKey.setText(json.getString("key"));
                this.viewHolder.textViewValue.setText(json.getString("value"));
                break;
            }

        } catch (JSONException e) {
            e.printStackTrace();
        }

        return container;
    }

}

这是我的日志返回的内容:

  

10-26 09:42:30.568:D / PerfilInfoAdapter(17228):中的项目数   阵列:11

另一个重要信息是我的ListView位于另一个GridView中,它有4种不同的视图,gridView工作正常,但不是ListView。

public class PerfilAdapter extends BaseAdapter {

    private List<JSONObject> jsonList;
    private Activity activity;
    private PerfilHelper helper;
    private ImageLoader imageLoader;
    private ViewHolder viewHolder;
    private boolean exibirFull;

    public static final int VIEW_TYPE_FOTO_PRINCIPAL = 0;
    public static final int VIEW_TYPE_INFO = 1;
    public static final int VIEW_TYPE_INFO_LIST = 2;
    public static final int VIEW_TYPE_GALERIA = 3;

    public PerfilAdapter(Activity activity, List<JSONObject> json, PerfilHelper helper) {
        this.activity = activity;
        this.helper = helper;
        this.jsonList = json;
        this.exibirFull = true;

        if (!ImageLoader.getInstance().isInited()) {
            ImageLoader.getInstance().init(new ImageLoaderConfiguration.Builder(this.activity).build());
        }
        imageLoader = ImageLoader.getInstance();
    }

    public void exibirFull(boolean exibir) {
        this.exibirFull = exibir;
        this.notifyDataSetChanged();
    }

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

    @Override
    public Object getItem(int i) {
        return this.jsonList.get(i);
    }

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

    @Override
    public int getItemViewType(int position) {

        int retorno = -1;

        if (this.jsonList.get(0).has("foto")) {
            if (position == 0) {
                retorno = VIEW_TYPE_FOTO_PRINCIPAL;
            }
            else if (position == 1) {
                retorno =  VIEW_TYPE_INFO;
            }
            else if (position == 2) {
                if (this.exibirFull) {
                    retorno =  VIEW_TYPE_INFO_LIST;
                }
                else {
                    retorno = VIEW_TYPE_GALERIA;
                }
            }
            else {
                retorno = VIEW_TYPE_GALERIA;
            }
        }
        else {
            if (position == 0) {
                retorno =  VIEW_TYPE_INFO;
            }
            else if (position == 1) {
                if (this.exibirFull) {
                    retorno =  VIEW_TYPE_INFO_LIST;
                }
                else {
                    retorno = VIEW_TYPE_GALERIA;
                }
            }
            else {
                retorno = VIEW_TYPE_GALERIA;
            }
        }

        return retorno;
    }

    @Override
    public int getViewTypeCount() {
        return 4;
    }

    public void updateJsonPerfil(List<JSONObject> json) {
        this.jsonList = json;
        this.notifyDataSetChanged();
    }

    @Override
    public View getView(int i, View container, ViewGroup viewGroup) {
        this.viewHolder = null;

        int type = this.getItemViewType(i);

        if (container == null) {
            this.viewHolder = new ViewHolder();

            switch (type) {
                case VIEW_TYPE_FOTO_PRINCIPAL:
                    container = this.activity.getLayoutInflater().inflate(R.layout.perfil_foto, viewGroup, false);

                    this.viewHolder.imageView = (ImageView) container.findViewById(R.id.perfil_foto_imageView);
                    break;
                case VIEW_TYPE_INFO:
                    container = this.activity.getLayoutInflater().inflate(R.layout.perfil_info, viewGroup, false);

                    this.viewHolder.textViewApelido = (TextView) container.findViewById(R.id.perfil_info_apelido);
                    this.viewHolder.textViewCidade = (TextView) container.findViewById(R.id.perfil_info_textVewCidade);
                    this.viewHolder.textViewDistancia = (TextView) container.findViewById(R.id.perfil_info_textViewDistancia);
                    break;
                case VIEW_TYPE_INFO_LIST:
                    container = this.activity.getLayoutInflater().inflate(R.layout.perfil_info_list, viewGroup, false);

                    this.viewHolder.listViewInfo = (ListView) container.findViewById(R.id.perfil_info_list_listView);               
                    break;
                case VIEW_TYPE_GALERIA:
                    container = this.activity.getLayoutInflater().inflate(R.layout.perfil_info, viewGroup, false);
                    break;
            }

            container.setTag(this.viewHolder);
        }
        else {
            this.viewHolder = (ViewHolder)container.getTag();
        }

        if (this.jsonList.size() > 0) {
            JSONObject json = this.jsonList.get(i);

            try {
                if (type == VIEW_TYPE_FOTO_PRINCIPAL) {
                    JSONObject foto = json.getJSONObject("foto");
                    this.imageLoader.displayImage(foto.getString("full"), this.viewHolder.imageView);
                }
                else if (type == VIEW_TYPE_INFO) {
                    JSONObject perfil = json.getJSONObject("perfil");
                    this.viewHolder.textViewApelido.setText(perfil.getString("apelido"));
                    this.viewHolder.textViewCidade.setText(perfil.getString("cidade"));
                    this.viewHolder.textViewDistancia.setText(perfil.getString("distancia"));
                }
                else if (type == VIEW_TYPE_INFO_LIST) {

                    // This is where i use the second ListView
                    this.viewHolder.listViewInfo.setAdapter(new PerfilInfoAdapter(this.activity, json.getJSONArray("info")));

                }
                else {
                    Log.d("PerfilAdapter", "Populando: VIEW_TYPE_GALERIA");
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        return container;
    }

    protected class ViewHolder {
        ImageView imageView;

        TextView textViewApelido;
        TextView textViewCidade;
        TextView textViewDistancia;

        ListView listViewInfo;
    }

}

我尝试将ListView更改为GridView,但问题出在适配器上。

任何人都可以帮助我吗?我很感激!

2 个答案:

答案 0 :(得分:1)

您的第一个问题:尝试合并ListViewGridView。永远不会永远将一个放在另一个之内。当你注意到时,你会遇到各种各样的问题。第一个大问题是滚动。当可滚动视图嵌入另一个滚动视图并且都滚动相同方向时,Android不喜欢它。来自Android员工的Comical sketch有关此问题。这样做只有在水平滚动而另一个垂直滚动时才可行。

您的下一个重大问题是将ListAdapter嵌入另一个ListAdapter。您必须记住,每个位置可以调用getView()方法3-4次。当你为每个位置嵌入另一个适配器时,它本身将被调用3-4次,而它自己的位置......神圣的性能命中!这有不好的想法写在它上面。

我看到的问题是您的JSONArray / List引用。 PerfilInfoAdapter维护对用于实例化它的JSONArray的相同引用...这与PerfilAdapter List引用的数据相同。此外,PerfilAdapter维护着由使用它的人引用的相同列表。这会设置一个危险的引用链,如果您不小心,可能会在修改时导致问题。理想情况下,每个适配器应在ListJSONArray实例上保留相同的数据。

总而言之,答案是改变您的设计选择。除了在垂直滚动内需要垂直滚动之外,还有其他方式可以显示数据。如果ListView不需要滚动,请使用LinearLayout。如果GridView不需要滚动,请使用TableLayoutGridLayout。或者通过提出不同的UI来完全改变用户体验。

作为旁注,如果您需要完整的JSONArray适配器,请查看Advanced-Adapters。 JSONAdapter将在一周左右发布,可以在Redesign分支上找到。它的代码完整,只是支持发布的演示应用程序。

答案 1 :(得分:0)

如何正确实现getItem(不返回null)?

或者我更喜欢

  1. 制作POJO类并将JSON转换为它。 (比如使用GSON
  2. 扩展ArrayAdapter而非BaseAdapter,以便您不必实施所有抽象方法。