在操作栏列表菜单中使用自定义适配器时使用Nullpointer(使用compat-v7)

jad*_*sta 10 android android-actionbar android-support-library android-actionbar-compat

当使用最新版本的兼容性lib(即compat-lib的v18,与4.3 Android版本一起发布)并使用操作栏中的列表导航菜单模式时,我将遇到Nullpointer异常.该错误发生在2.3.3版本的android中.我相信这是因为在这个版本(以及其他版本)中,使用的整个操作栏代码是compat-lib代码.

当我点击列表菜单(在操作栏上)时,我的应用程序崩溃,我在logcat收到以下错误:

07-30 18:17:59.296: E/AndroidRuntime(14701): FATAL EXCEPTION: main
07-30 18:17:59.296: E/AndroidRuntime(14701): java.lang.NullPointerException
07-30 18:17:59.296: E/AndroidRuntime(14701):    at android.support.v7.internal.widget.ListPopupWindow$DropDownListView.measureHeightOfChildrenCompat(ListPopupWindow.java:1317)
07-30 18:17:59.296: E/AndroidRuntime(14701):    at android.support.v7.internal.widget.ListPopupWindow.buildDropDown(ListPopupWindow.java:1062)
07-30 18:17:59.296: E/AndroidRuntime(14701):    at android.support.v7.internal.widget.ListPopupWindow.show(ListPopupWindow.java:514)
07-30 18:17:59.296: E/AndroidRuntime(14701):    at android.support.v7.internal.widget.SpinnerICS$DropdownPopup.show(SpinnerICS.java:758)
07-30 18:17:59.296: E/AndroidRuntime(14701):    at android.support.v7.internal.widget.SpinnerICS.performClick(SpinnerICS.java:443)
07-30 18:17:59.296: E/AndroidRuntime(14701):    at android.view.View$PerformClick.run(View.java:9109)
07-30 18:17:59.296: E/AndroidRuntime(14701):    at android.os.Handler.handleCallback(Handler.java:587)
07-30 18:17:59.296: E/AndroidRuntime(14701):    at android.os.Handler.dispatchMessage(Handler.java:92)
07-30 18:17:59.296: E/AndroidRuntime(14701):    at android.os.Looper.loop(Looper.java:130)
07-30 18:17:59.296: E/AndroidRuntime(14701):    at android.app.ActivityThread.main(ActivityThread.java:3683)
07-30 18:17:59.296: E/AndroidRuntime(14701):    at java.lang.reflect.Method.invokeNative(Native Method)
07-30 18:17:59.296: E/AndroidRuntime(14701):    at java.lang.reflect.Method.invoke(Method.java:507)
07-30 18:17:59.296: E/AndroidRuntime(14701):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:895)
07-30 18:17:59.296: E/AndroidRuntime(14701):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:653)
07-30 18:17:59.296: E/AndroidRuntime(14701):    at dalvik.system.NativeStart.main(Native Method)
Run Code Online (Sandbox Code Playgroud)

这是下拉单元格的xml(称为item_menu_dropdown_celula.xml):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@drawable/spinner_subitem_background_ab_boadicatema"
    android:gravity="center"
    android:minHeight="?android:attr/listPreferredItemHeight"
    android:orientation="horizontal" >

    <ImageView
        android:id="@+id/icone"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dip"
        android:scaleType="fitCenter" />

    <TextView
        android:id="@+id/texto"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="5dip"
        android:gravity="left|center_vertical"
        android:shadowColor="@android:color/black"
        android:shadowDx="0"
        android:shadowDy="1"
        android:shadowRadius="0.1"
        android:textAppearance="?android:attr/textAppearanceMedium"
        android:textColor="@android:color/white"
        android:textStyle="bold" />

</LinearLayout>
Run Code Online (Sandbox Code Playgroud)

这是微调器适配器的代码:

public class SpinnerListMenu implements SpinnerAdapter{

    private List<ItemMenu> itens;
    private LayoutInflater inflater;

    public SpinnerListMenu(Context context, List<ItemMenu> listaItens) {
        this.itens = listaItens;
        this.inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

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

    @Override
    public ItemMenu getItem(int arg0) {
        return itens.get(arg0);
    }

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

    @Override
    public int getItemViewType(int position) {
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final ViewHolder holder;
        View row = convertView;

        if ((row == null) || (row.getTag() == null)) {

            row = inflater.inflate(R.layout.item_menu_celula, null); 
            holder = new ViewHolder(row);
            row.setTag(holder);
        } else {
            holder = (ViewHolder) row.getTag();
        }

        ItemMenu atual = getItem(position);

        holder.texto.setText(atual.getNomeDaArea());

        holder.icone.setBackgroundResource(atual.getIconeMenuFechadoResource());
        holder.icone.setScaleType(ScaleType.FIT_CENTER);

        return row;
    }

    private class ViewHolder {
        ImageView icone;
        TextView texto;

        public ViewHolder(View base) {
            icone = (ImageView) base.findViewById(R.id.icone);
            texto = (TextView) base.findViewById(R.id.texto);
        }
    }

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

    @Override
    public boolean hasStableIds() {
        return false;
    }

    @Override
    public boolean isEmpty() {
        return itens.size() == 0;
    }

    @Override
    public void registerDataSetObserver(DataSetObserver observer) {

    }

    @Override
    public void unregisterDataSetObserver(DataSetObserver observer) {

    }

    @Override
    public View getDropDownView(int position, View convertView, ViewGroup parent) {
        final ViewHolderDD holder;
        View row = convertView;

        if ((row == null) || (row.getTag() == null)) {
            row = inflater.inflate(R.layout.item_menu_dropdown_celula, null);
            holder = new ViewHolderDD(row);
            row.setTag(holder);
        } else {
            holder = (ViewHolderDD) row.getTag();
        }

        ItemMenu atual = getItem(position);

        holder.texto.setText(atual.getNomeDaArea());
        holder.icone.setBackgroundResource(atual.getIconeMenuAbertoResource());

        return row;
    }

    private class ViewHolderDD {
        ImageView icone;
        TextView texto;

        public ViewHolderDD(View base) {
            icone = (ImageView) base.findViewById(R.id.icone);
            texto = (TextView) base.findViewById(R.id.texto);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在活动中,我使用代码设置菜单和他的适配器:

//This class correctly extends ActionBarActivity
//here we area inside onCreate method
getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
ArrayList<ItemMenu> itens = = new ArrayList<ItemMenu>();

//Here I add 2 itens in the arraylist
//...
getSupportActionBar().setListNavigationCallbacks(
                new SpinnerListMenu(this, itens), this);
Run Code Online (Sandbox Code Playgroud)

更多信息,以帮助.在我的活动中,我使用数组适配器,如...

SpinnerAdapter mSpinnerAdapter = ArrayAdapter.createFromResource(this, R.array.action_list,
          android.R.layout.simple_spinner_dropdown_item);
Run Code Online (Sandbox Code Playgroud)

它的工作原理,错误不会发生.

有没有人知道导致这个bug的原因是什么?(或者即使这是来自兼容性lib本身的错误(这是我的猜测,在查看堆栈跟踪并更改我的xml的许多属性之后))

jad*_*sta 27

在Android的问题跟踪器中发布此问题后,我从Android项目成员那里得到了一个更好的答案(比我的旧答案).纠正这个问题的正确方法是更换线路

row = inflater.inflate(R.layout.item_menu_dropdown_celula, null); 
Run Code Online (Sandbox Code Playgroud)

按行

row = inflater.inflate(R.layout.item_menu_dropdown_celula, parent, false);
Run Code Online (Sandbox Code Playgroud)