1

我正在使用 HTC Desire (Gingerbread 2.3.7) 和 Google Nexus 7 (Jelly Bean 4.3) 开发我的 Android 项目。我需要将一些数据从 MainActivity 发送到 InfoActivity,所以我使用了一个意图。在这个 InfoActivity 中,我还在操作栏中有一个菜单项来刷新信息。

在此处输入图像描述

在 InfoActivity 中,我向用户显示数据。但这不是问题,问题出在菜单上。看下面的代码:

public class ShowInfoActivity extends ActionBarActivity {

    private MenuItem menuItem   = null;
    // ...

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // ...
        new OneTask().execute(...);
        // ...
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        case R.id.refresh:
            menuItem = item;
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
    }

    private class OneTask extends AsyncTask<Object, Void, String> {
        // ...
        @Override
        protected void onPreExecute() {
            MenuItemCompat.setActionView(menuItem,
                        R.layout.actionbar_indeterminate_progress);
            MenuItemCompat.expandActionView(menuItem);
        }
        // ...
        @Override
        protected void onPostExecute(String result) {
            MenuItemCompat.collapseActionView(menuItem);
            MenuItemCompat.setActionView(menuItem, null);
        }
    }

很显然,第一次执行时,menuItem=null,所以它一定会崩溃。令人难以置信的是,在 HTC 中它运行良好,但在 Nexus 中它显然崩溃了。为什么这在设备之间有所不同?

PS:我已经解决了,但我想知道为什么这种行为......

4

2 回答 2

1

如有疑问,请始终检查源代码。如果您查看 MenuItemCompat.java,您会发现它基于 API 级别进行切换,如下所示:

    static final MenuVersionImpl IMPL;
    static {
        final int version = android.os.Build.VERSION.SDK_INT;
        if (version >= 14) {
            IMPL = new IcsMenuVersionImpl();
        } else if (version >= 11) {
            IMPL = new HoneycombMenuVersionImpl();
        } else {
            IMPL = new BaseMenuVersionImpl();
        }
    }

基本实现(用于 2.3 设备)的基本 setActionView 方法只返回 MenuItem,因此它永远不会抛出异常:

@Override
public MenuItem setActionView(MenuItem item, View view) {
    return item;
}

另一方面,HoneycombMenuVersionImpl 委托给另一个类:

        @Override
        public boolean setShowAsAction(MenuItem item, int actionEnum) {
            MenuItemCompatHoneycomb.setShowAsAction(item, actionEnum);
            return true;
        }

并且委托类尝试调用 MenuItem 上的实际方法,这将引发异常:

public static void setShowAsAction(MenuItem item, int actionEnum) {
    item.setShowAsAction(actionEnum);
}

在这个特定的示例中,检查源代码可以回答您的问题,并向您展示处理不同 Android 版本之间兼容性的可靠策略。

于 2013-10-01T20:24:18.630 回答
0

setActionView()/collapseActionView() 是 Android 4 中的本机函数...传递 null MenuItem 肯定会不受欢迎。

在您的 Android 2.3 设备上,兼容性库 (android.support.v4) 具有自己的 setActionView()/collapseActionView() 内部实现,这些实现可能对错误输入更具弹性。

于 2013-10-01T18:13:13.920 回答