Loader calls onLoadFinished before Activity's onCreateOptionsMenu
When an AsynctaskLoader
is initiated from Activity's OnCreate()
, it finishes its work and calls onLoaderFinished()
before action bar menu is inflated, that is before onCreateOptionsMenu()
is called.
I need to alter some action menu items depending on results of loader. What approach might resolve this ?
UPDATE: This happens On orientation change. I'm Observing this sequence in debugger:
onCreate()
-> onCreateOptionsMenu()
-> onLoadFinished()
onCreate()
-> onLoadFinished()
-> onCreateOptionsMenu()
onCreate()
-> onLoadFinished()
-> onCreateOptionsMenu()
I ran into the same scenario when trying to call shareActionProvider.setShareIntent()
in onLoadFinished()
which was dependent on shareActionProvider being initalized in onCreateOptionsMenu()
.
My solution was to scope both my Intent and ShareActionProvider to the Fragment, and then within each method initialize the appropriate field and set the other if it had already been defined. That way it works no matter which is called first without invalidating the menu.
Here's basically what it looks like
public class myFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> {
...
private ShareActionProvider shareActionProvider;
private Intent shareIntent;
...
onCreateOptionsMenu()
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_my_fragment, menu);
MenuItem menuItem = menu.findItem(R.id.action_share);
shareActionProvider = (ShareActionProvider) MenuItemCompat.getActionProvider(menuItem);
//in the case where onLoadFinished is called first, simply set the share intent here.
if (null != shareIntent)
{
shareActionProvider.setShareIntent(shareIntent);
}
}
onLoadFinished()
@Override
public void onLoadFinished(android.support.v4.content.Loader<Cursor> loader, Cursor data) {
... <get some data from cursor> ...
shareIntent = new Intent(Intent.ACTION_SEND);
shareIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
shareIntent.setType("text/plain");
shareIntent.putExtra(Intent.EXTRA_TEXT, getString(R.string.share_text)+data);
//shareActionProvider may be null due to onLoadFinished called before onCreateOptionsMenu
if (null != shareActionProvider)
{
shareActionProvider.setShareIntent(shareIntent);
}
I need to alter some action menu items depending on results of loader. What approach might resolve this ?
Your scenarios #2 and #3 should be perfectly fine for you, then. By the time onCreateOptionsMenu()
is called, you have your Cursor
(or whatever) from your Loader
and can tailor what you do in onCreateOptionsMenu()
.
With regards to scenario #1, have onCreateOptionsMenu()
do the most likely thing, and if you determine in onLoadFinished()
that this is incorrect, call invalidateOptionsMenu()
to force another call to onCreateOptionsMenu()
, I suppose.
This particular approach avoids invalidating entire menu.
Define one boolean flag, and one MenuItem variable for each item you want to control based on outcomes of loader results:
Let's say you want to enable New action only if loader returns any success:
private boolean mEnableNew = false;
private MenuItem mItemNew;
Save the menu item to variable when menu is created, also, apply state:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.manage_menu, menu);
mItemNew = menu.findItem(R.id.itm__manage_menu__new);
mItemNew.setEnabled(mEnableNew);
return super.onCreateOptionsMenu(menu);
}
Finally, obtain new settings based on Loader's results, and enable disable menu item:
@Override
public void onLoadFinished(Loader<BI_Result> loader, Result result) {
//--If onCreateOptionsMenu is not yet executed,it will use this boolean value when it does
mEnableNew = result.isSuccess();
//--If onCreateOptionsMenu has executed, we apply state here
if (mItemNew != null) {
mItemNew.setEnabled(mEnableNew);
}
}
链接地址: http://www.djcxy.com/p/11208.html