Marcel Ulbrich
Marcel Ulbrich

Reputation: 75

Preload all Fragments' Views?

Initial Situation:

Hi, I am currently working on an update for an existing app and have problems with one particular activity. It contains 7 tabs and in those tabs there are several imagebuttons and textviews for different methods.

In the original version of the app I used a tabhost and basically had all the content necessary in one xml file and one java file, but it was not possible to swipe the tabcontent sideways to change tabs, so I created the entire thing again with fragments.

Challenge:

In the ActionBar, I have a Filter Button, that is supposed to hide certain textviews and imagebuttons from ALL tabs, by checking a flag and then calling methods in all the 7 fragment classes, which then set views in their rootView to GONE and if toggled again, to VISIBLE.

Problem:

This ActionBar button works fine, if users scroll through all the tabs first, but if clicked on a cold start of the app, it will crash the app with NullPointer Exceptions. I suspect this is, because not all fragments are loaded yet.

Question:

Should I preload all fragments at the start of the activity? If so, how would I do that and in what file would that be accomplished? Is there another, maybe better way, to make sure, I can manipulate all tabs/fragments from the ActionBar, even if I don't know, what fragments have been opened before? Should I mash all those methods in one global one? In what file would it go?

Currently, it only works, if you scroll through all the tabs first, then I can toggle the filter as often as I want.

Code:

This is called in the Activity Class:

    public void toggleintroonly() {
    MenuItem toggle = menu.findItem(R.id.mtoggle);

    if (visible == 1) {
        Fragments1.toggleintroonly();
        Fragments2.toggleintroonly();
        Fragments3.toggleintroonly();
        Fragments4.toggleintroonly();
        Fragments5.toggleintroonly();
        Fragments6.toggleintroonly();
        Fragments7.toggleintroonly();
        toggle.setTitle(getString(R.string.menu4toggled));
        toggle.setIcon(R.drawable.ic_action_showall);
        visible = 0;
    } else {
        Fragments1.showall();
        Fragments2.showall();
        Fragments3.showall();
        Fragments4.showall();
        Fragments5.showall();
        Fragments6.showall();
        Fragments7.showall();
        toggle.setTitle(getString(R.string.menu4));
        toggle.setIcon(R.drawable.ic_action_filter);
        visible = 1;
    }
}

This is a sample from Fragments1.toggleintroonly():

public static void toggleintroonly() {
    rootView.findViewById(R.id.tv1x02).setVisibility(View.GONE);
    rootView.findViewById(R.id.bplay1x02).setVisibility(View.GONE);
    rootView.findViewById(R.id.bshare1x02).setVisibility(View.GONE);
    rootView.findViewById(R.id.binfo1x02).setVisibility(View.GONE);
    rootView.findViewById(R.id.bring1x02).setVisibility(View.GONE);
}

Here is the error when the Filter Button from the ActionBar is clicked , right after the Activity is launched:

10-27 16:43:34.923: E/MediaPlayer(16946): mOnCompletionListener is null. Failed to send MEDIA_PLAYBACK_COMPLETE message.
10-27 16:43:49.433: D/AndroidRuntime(16946): Shutting down VM
10-27 16:43:49.433: W/dalvikvm(16946): threadid=1: thread exiting with uncaught exception (group=0x40c511f8)
10-27 16:43:49.448: E/AndroidRuntime(16946): FATAL EXCEPTION: main
10-27 16:43:49.448: E/AndroidRuntime(16946): java.lang.NullPointerException
10-27 16:43:49.448: E/AndroidRuntime(16946):    at com.cheftony.psychsoundboard.Fragments3.toggleintroonly(Fragments3.java:225)
10-27 16:43:49.448: E/AndroidRuntime(16946):    at com.cheftony.psychsoundboard.NicknamesNew.toggleintroonly(NicknamesNew.java:121)
10-27 16:43:49.448: E/AndroidRuntime(16946):    at com.cheftony.psychsoundboard.NicknamesNew.onOptionsItemSelected(NicknamesNew.java:90)
10-27 16:43:49.448: E/AndroidRuntime(16946):    at android.app.Activity.onMenuItemSelected(Activity.java)
10-27 16:43:49.448: E/AndroidRuntime(16946):    at android.support.v4.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:353)
10-27 16:43:49.448: E/AndroidRuntime(16946):    at com.android.internal.policy.impl.PhoneWindow.onMenuItemSelected(PhoneWindow.java)
10-27 16:43:49.448: E/AndroidRuntime(16946):    at com.android.internal.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java)
10-27 16:43:49.448: E/AndroidRuntime(16946):    at com.android.internal.view.menu.MenuItemImpl.invoke(MenuItemImpl.java)
10-27 16:43:49.448: E/AndroidRuntime(16946):    at com.android.internal.view.menu.MenuBuilder.performItemAction(MenuBuilder.java)
10-27 16:43:49.448: E/AndroidRuntime(16946):    at com.android.internal.view.menu.ActionMenuView.invokeItem(ActionMenuView.java)
10-27 16:43:49.448: E/AndroidRuntime(16946):    at com.android.internal.view.menu.ActionMenuItemView.onClick(ActionMenuItemView.java)
10-27 16:43:49.448: E/AndroidRuntime(16946):    at android.view.View.performClick(View.java)
10-27 16:43:49.448: E/AndroidRuntime(16946):    at android.view.View$PerformClick.run(View.java)
10-27 16:43:49.448: E/AndroidRuntime(16946):    at android.os.Handler.handleCallback(Handler.java)
10-27 16:43:49.448: E/AndroidRuntime(16946):    at android.os.Handler.dispatchMessage(Handler.java)
10-27 16:43:49.448: E/AndroidRuntime(16946):    at android.os.Looper.loop(Looper.java)
10-27 16:43:49.448: E/AndroidRuntime(16946):    at android.app.ActivityThread.main(ActivityThread.java)
10-27 16:43:49.448: E/AndroidRuntime(16946):    at java.lang.reflect.Method.invokeNative(Native Method)
10-27 16:43:49.448: E/AndroidRuntime(16946):    at java.lang.reflect.Method.invoke(Method.java:511)
10-27 16:43:49.448: E/AndroidRuntime(16946):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java)
10-27 16:43:49.448: E/AndroidRuntime(16946):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java)
10-27 16:43:49.448: E/AndroidRuntime(16946):    at dalvik.system.NativeStart.main(Native Method)

The error seems to be caused in the Fragments3 class, because upon start of the Activity, Fragments1 is active and its direct neighbour Fragments2 is preloaded as well.

Upvotes: 4

Views: 3915

Answers (1)

Alex Lockwood
Alex Lockwood

Reputation: 83311

A couple suggestions:

  1. If you are working with 7 tabs, you might consider using a ViewPager instead. It will help quicken the user experience. :)

  2. Make sure your Fragments don't assume the Activity has been created until onActivityCreated() has been called. This could be why you are getting a NullPointerException.

  3. Your Fragments should serve as independent UI components. If your Fragments are interacting with each other, you might want to rethink your design, as it is likely complicating things.

  4. Unless your Fragments take a crazy long time to be created/displayed, I'm not sure preloading the Fragments is necessary. With 7 tabs, the user might not use all of the Fragments, so loading all of them might be wasteful. Preloading a select few would also make no sense, since you can never know which tab the user will pick next. It sounds to me that the best solution would to just initialize a new Fragment and fill the tab's view with it when the user clicks on the tab.

Upvotes: 2

Related Questions