1

我正在使用 CursorLoader 从片段中的 SQLite 获取一些数据。为此的 initLoader() 在 onActivityCreated() 中执行...

public class MyFragment extends Fragment implements LoaderCallbacks<Cursor>
{
    MenuItem menuItemOne;

    @Override
    public void onActivityCreated(Bundle savedInstanceState)
    {
        super.onActivityCreated(savedInstanceState);
        getLoaderManager().initLoader(0, null, this);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
    {
        inflater.inflate(R.menu.myMenu, menu);
        menuItemOne = menu.findItem(R.id.menuItemOne);
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor)
    {
        menuItemOne.doSomething();
    }
}

为便于阅读,对上述代码进行了简化。这是我的问题...

  • Nexus S上,没有问题
  • Nexus 7上,空指针出现在 onLoadFinished 中。menuItemOne 在这里为空。

Nexus S 使用的是 Android 4.1.2,而 Nexus 7 使用的是 Android 4.2.2。

  • 我应该在其他地方运行 initLoader() 吗?
  • 您认为 Android 版本存在错误/差异吗?
4

2 回答 2

1

它们是不同的设备,因此肯定存在差异。

但也许/很可能这是您看到的更微妙的错误。N7 上的数据库访问速度比 Nexus S 上快得多。这样,即使在创建菜单之前,也会调用 onLoadFinished。

这段代码中的主要错误是它依赖于异步和完全独立的进程来按定义的顺序完成。

您可以尝试开始加载不同的回调或执行一些类似以下代码的方案来保证执行:

Cursor c;

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
{
    inflater.inflate(R.menu.myMenu, menu);
    menuItemOne = menu.findItem(R.id.menuItemOne);
    loadFinishMenuInflated();
}

@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor cursor)
{
     c = cursor;
     loadFinishMenuInflated();
}

private void loadFinishMenuInflated(){
    if(c!=null && menuItemOne!=null){
       // do something...
    }
}

这样你就可以保证// do something只有在两个项目都初始化后才执行。

于 2013-04-09T13:16:17.793 回答
1

这是我的另一个想法:

public class MyFragment extends Fragment implements LoaderCallbacks<Cursor>
{
    MenuItem menuItemOne;
    boolean executeMenuItemAction = false;

    @Override
    public void onActivityCreated(Bundle savedInstanceState)
    {
        super.onActivityCreated(savedInstanceState);
        getLoaderManager().initLoader(0, null, this);
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater)
    {
        inflater.inflate(R.menu.myMenu, menu);
        menuItemOne = menu.findItem(R.id.menuItemOne);
        if(executeMenuItemAction )
            menuItemOne.doSomething();
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor)
    {
        executeMenuItemAction = true;
        getActivity.invalidateOptionsMenu(); //or getActivity().supportInvalidateOptionsMenu() if you are using sherlock
    }
}
于 2013-04-09T13:25:38.047 回答