initLoader()和onCreateOptionsMenu()可能的线程错误/问题

时间:2013-04-09 13:06:41

标签: android

我使用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版本存在错误/差异吗?

2 个答案:

答案 0 :(得分:1)

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

但也许/可能是你看到的更微妙的错误。 N7上的DB访问速度比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仅在两个项目初始化后才执行。

答案 1 :(得分: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
    }
}