Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Loader calls onLoadFinished before Activity's onCreateOptionsMenu

Tags:

android

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:

  1. Application Start: onCreate() -> onCreateOptionsMenu() -> onLoadFinished()
  2. Rotate to landscape: onCreate() -> onLoadFinished() -> onCreateOptionsMenu()
  3. Rotate back to portrait: onCreate() -> onLoadFinished() -> onCreateOptionsMenu()
like image 356
S.D. Avatar asked Sep 25 '12 18:09

S.D.


2 Answers

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);
    }
like image 159
dcwilcox Avatar answered Oct 26 '22 13:10

dcwilcox


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.

like image 21
CommonsWare Avatar answered Oct 26 '22 12:10

CommonsWare