Changing between Navigation Drawer fragments is slow

  • Replies:29
Amitai Rosenberg
  • Forum posts: 27

Jun 1, 2016, 2:10:58 PM via Website

I have an app with a Navigation Drawer that uses fragments for each menu item.
Each time an item is clicked, I replace the current fragment.

The problem is that it takes a long time to show the new fragment after the user clicked.
The fragment that takes the longest to load is a fragment that has also tabs inside it with child fragments.
Is there any way I can speed up the loading of the fragments? (Perhaps initializing them beforehand, if this is possible?)

Here is my code:

protected override void OnCreate(Bundle bundle)
{
    drawerLayout = FindViewById<DrawerLayout>(Resource.Id.drawer_layout);
    navigationView = FindViewById<NavigationView>(Resource.Id.nav_view);
    drawerLayout.DrawerClosed += DrawerLayout_DrawerClosed;
    var mainFab = FindViewById<FloatingActionButton>(Resource.Id.mainFab);
    mainFab.Click += MainFab_Click;

    var callFab = FindViewById<FloatingActionButton>(Resource.Id.callFab);
    callFab.Click += CallFab_Click;
    var messageFab = FindViewById<FloatingActionButton>(Resource.Id.messageFab);
    messageFab.Click += MessageFab_Click;
    // Initialize the ViewPager and set an adapter
    //var pager = FindViewById<ViewPager>(Resource.Id.pager);
    //pager.Adapter = new TabsFragmentPagerAdapter(SupportFragmentManager, fragments, titles);

    // Bind the tabs to the ViewPager
    //var tabs = FindViewById<PagerSlidingTabStrip>(Resource.Id.tabs);
    //tabs.SetViewPager(pager);

    navigationView.NavigationItemSelected += (sender, e) =>
    {
        e.MenuItem.SetChecked(true);
        //react to click here and swap fragments or navigate

        switch (e.MenuItem.ItemId)
        {
            case (Resource.Id.nav_home):
                ListItemClicked(0);
                break;

            case (Resource.Id.nav_halachot):
                ListItemClicked(1);
                break;

            case (Resource.Id.nav_times):
                ListItemClicked(2);
                break;

            case (Resource.Id.nav_siddur):
                ListItemClicked(3);
                break;
            case (Resource.Id.nav_compass):
                ListItemClicked(4);
                break;

            case (Resource.Id.nav_settings):
                ListItemClicked(5);
                break;
        }


        drawerLayout.CloseDrawers();                
    };

    if (bundle == null)
    {
        ListItemClicked(0);
        navigationView.Menu.GetItem(0).SetChecked(true);
        fragment = new HomeFragment();
        SupportFragmentManager.BeginTransaction()
        .Replace(Resource.Id.content_frame, fragment)
        .Commit();
    }
}

public override void OnBackPressed()
{

    if (drawerLayout.IsDrawerOpen((int)GravityFlags.Start))
    {
        drawerLayout.CloseDrawer((int)GravityFlags.Start);
    }
    else
    {
        base.OnBackPressed();
    }
}

private void ListItemClicked(int position)
{

    switch (position)
    {
        case 0:
            fragment = new HomeFragment();
            Title = "Home";
            SupportActionBar.Elevation = 8;
            break;
        case 1:
            fragment = new HalachaFragment();
            Title = "aaa";
            SupportActionBar.Elevation = 0;
            break;
        case 2:
            fragment = new TimesFragment();
            Title = "bbb";
            SupportActionBar.Elevation = 8;

            break;
        case 3:
            fragment = new SiddurFragment();
            Title = "ccc";
            SupportActionBar.Elevation = 8;
            break;
        case 4:
            fragment = new CompassFragment();
            Title = "ddd";
            SupportActionBar.Elevation = 8;
            break;
        case 5:
            fragment = new SettingsFragment();
            Title = "eee";
            break;
    }



}

private void DrawerLayout_DrawerClosed(object sender, DrawerLayout.DrawerClosedEventArgs e)
{
    SupportFragmentManager.BeginTransaction()
        .Replace(Resource.Id.content_frame, fragment).AddToBackStack("BACK")
        .Commit();

}

HalachaFragment.cs (The fragment that contains the tabs):

public class HalachaFragment : Fragment
{
    private ViewPager halachotPager;
    private PagerSlidingTabStrip tabs;

public HalachaFragment()
{
    this.RetainInstance = true;
}
public override void OnCreate(Bundle savedInstanceState)
{
    base.OnCreate(savedInstanceState);

    // Create your fragment here
}

public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
    // Use this to return your custom view for this Fragment

    var view = inflater.Inflate(Resource.Layout.HalachaSection, container, false);

    var fragments = new Android.Support.V4.App.Fragment[]
   {
       new HalachotFragment(),
       new BooksFragment(),
   };

    var titles = CharSequence.ArrayFromStringArray(new[]
    {
            "הלכות",
            "ספרים",
    });

    halachotPager = view.FindViewById<ViewPager>(Resource.Id.halachotPager);

    halachotPager.Adapter = new TabsFragmentPagerAdapter(this.ChildFragmentManager, fragments, titles);
    halachotPager.OffscreenPageLimit = 2;
    halachotPager.SetCurrentItem(1, true);
    // Bind the tabs to the ViewPager
    tabs = view.FindViewById<PagerSlidingTabStrip>(Resource.Id.halachotTabs);

    tabs.SetViewPager(halachotPager);

    return view;

}

}

Hope someone can help me.

Thanks.

damponting44

Reply
Vladimir S.
  • Forum posts: 266

Jun 1, 2016, 2:31:30 PM via Website

Hello,

Does this problem present both on real device and on the emulator?

damponting44

Reply
Amitai Rosenberg
  • Forum posts: 27

Jun 1, 2016, 2:32:33 PM via Website

@Vladimir I can't get the emulator to work, so I'm only using a real device.

damponting44

Reply
Amitai Rosenberg
  • Forum posts: 27

Jun 2, 2016, 7:39:00 PM via Website

Anyone?

damponting44

Reply
Vladimir S.
  • Forum posts: 266

Jun 2, 2016, 8:02:03 PM via Website

Maybe this will help stackoverflow

damponting44

Reply
Amitai Rosenberg
  • Forum posts: 27

Jun 2, 2016, 8:05:32 PM via Website

Thanks, but I already did that, and replaced the fragments onDrawerClosed, but it still has a lag.

Reply
Vladimir S.
  • Forum posts: 266

Jun 2, 2016, 8:39:20 PM via Website

Do you use hardware acceleration? If not, add android:hardwareAccelerated="true" to the manifest.

— modified on Jun 2, 2016, 8:39:52 PM

damponting44

Reply
Amitai Rosenberg
  • Forum posts: 27

Jun 2, 2016, 8:40:39 PM via Website

Tried that. Didn't help :(

Reply
Vladimir S.
  • Forum posts: 266

Jun 2, 2016, 9:00:38 PM via Website

Sometimes a lot of data transfering between your test device and PC may slow it down. Did you try to disconnect usb cable after app installation?

damponting44

Reply
Amitai Rosenberg
  • Forum posts: 27

Jun 2, 2016, 9:02:48 PM via Website

Yes, it happens even when the device isn't connected.

Reply
mobilga com
  • Forum posts: 7

Jun 2, 2016, 9:06:21 PM via Website

Well, good to read that here nice and good topic under discussion. I really like this.

Reply
Vladimir S.
  • Forum posts: 266

Jun 2, 2016, 9:37:19 PM via Website

@Amitai can you post some screenshots or video of your app?

Reply
Amitai Rosenberg
  • Forum posts: 27

Jun 2, 2016, 10:43:47 PM via Website

Here's a link to a video of my app demonstrating this:

Notice that the second fragment takes the longest to load and that it shows the animation only on the second time I open it.

Thanks for your investigation and trying to help. I really appreciate it!

Vladimir S.

Reply
Vladimir S.
  • Forum posts: 266

Jun 2, 2016, 10:53:25 PM via Website

  1. Why do you use two TabsFragmentPagerAdapter. There are not tabs in top level of menu, try to use simple FragmentPagerAdapter, which can load all fragments in memory and theoretically would be better.
  2. Redusing images size to minimal suitable dimensions and using of the indexed colors can help

— modified on Jun 3, 2016, 7:32:17 AM

damponting44

Reply
Amitai Rosenberg
  • Forum posts: 27

Jun 4, 2016, 8:29:12 PM via Website

Sorry, but I didn't quite understand you. Where am I using 'two' TabsFragmentPagerAdapter?

— modified on Jun 4, 2016, 8:43:40 PM

damponting44

Reply
Vladimir S.
  • Forum posts: 266

Jun 4, 2016, 8:39:20 PM via Website

Oh, i haven't noticed what there are comments...

Reply
Amitai Rosenberg
  • Forum posts: 27

Jun 4, 2016, 8:43:26 PM via Website

:)
Any other ideas on performance? What are indexed colors?

damponting44

Reply
Amitai Rosenberg
  • Forum posts: 27

Jun 4, 2016, 9:15:50 PM via Website

Is there a way to initialize the fragment before opening it, so that once it is opened it will be loaded and won't lag?

Reply
Vladimir S.
  • Forum posts: 266

Jun 4, 2016, 9:22:24 PM via Website

Indexed color saves a lot of memory and storage space - your layout will be inflated more quickly. Most of grafics editor can convert pics to the indexed color format.

damponting44

Reply
Amitai Rosenberg
  • Forum posts: 27

Jun 4, 2016, 9:43:08 PM via Website

Thanks. I managed to minimize the lag by hardware acceleration, removing animation and unnecessary code. Although even when I don't put any image in the second fragment (the one with the tabs), there is a small lag that doesn't happen when I click on the others or when I open the same fragment a second time.

Is there a way to initialize the fragment before opening it, so that once it is opened it will be loaded and won't lag?
Or any other suggestions?

Thanks!

— modified on Jun 4, 2016, 9:43:26 PM

damponting44

Reply
Vladimir S.
  • Forum posts: 266

Jun 4, 2016, 10:41:02 PM via Website

What if all fragments will be initialized in onCreate() ?

HomeFragment homeFragment;
HalachaFragment halachaFragment;
other fragments...........

Your Activity {

protected override void OnCreate(Bundle bundle)
{ 
other strings ..........
homeFragment = new HomeFragment();
halachaFragment = new HalachaFragment();
other fragments...........
}

private void ListItemClicked(int position)
{

    switch (position)
    {
        case 0:
            fragment = homeFragment;
            Title = "Home";
            SupportActionBar.Elevation = 8;
            break;
        case 1:
            fragment = halachaFragment;
            Title = "aaa";
            SupportActionBar.Elevation = 0;
            break;
other cases..........
}
}
.....................
}

— modified on Jun 4, 2016, 10:51:15 PM

Reply
Amitai Rosenberg
  • Forum posts: 27

Jun 4, 2016, 10:56:51 PM via Website

Interesting idea, although sadly the lag is still there in the second fragment :(

Reply
Amitai Rosenberg
  • Forum posts: 27

Jun 4, 2016, 10:58:16 PM via Website

Although it only happens on the first time it is clicked. Why is this?

Reply
Vladimir S.
  • Forum posts: 266

Jun 4, 2016, 11:05:03 PM via Website

When you select other fragment, previous one is not destroyed, but only detached and when it is recalled the FragmentManager extracts it from the backstack.

public override void OnCreate(Bundle savedInstanceState)
{
    base.OnCreate(savedInstanceState);

    // Create your fragment here
}

Maybe comment is right? :)

— modified on Jun 4, 2016, 11:08:02 PM

Reply
Amitai Rosenberg
  • Forum posts: 27

Jun 4, 2016, 11:07:47 PM via Website

Oh, I see. If any other idea comes up, I'll be glad. If you want to see some of my other code, I can post it.

Thanks!

Reply
Vladimir S.
  • Forum posts: 266

Jun 4, 2016, 11:14:41 PM via Website

I have edited my post and are not sure you read it after...

Maybe you need to init tab fragments in onCreate of HalachFragment? There is comment "Create your fragment here".

Reply
Amitai Rosenberg
  • Forum posts: 27

Jun 4, 2016, 11:25:03 PM via Website

Tried changing it to this:

public class HalachaFragment : Fragment
{
    private ViewPager halachotPager;
    private PagerSlidingTabStrip tabs;
    private Fragment[] fragments;
    TabsFragmentPagerAdapter tabsAdapter;

    public HalachaFragment()
    {
        this.RetainInstance = true;
    }
    public override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);

        fragments = new Fragment[]
       {
           new HalachotFragment(),
           new BooksFragment(),
       };

        var titles = CharSequence.ArrayFromStringArray(new[]
       {
                "הלכות",
                "ספרים",
        });

        tabsAdapter = new TabsFragmentPagerAdapter(ChildFragmentManager, fragments, titles);
        // Create your fragment here
    }

    public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        // Use this to return your custom view for this Fragment

        var view = inflater.Inflate(Resource.Layout.HalachaSection, container, false);


        halachotPager = view.FindViewById<ViewPager>(Resource.Id.halachotPager);

        halachotPager.Adapter = tabsAdapter;
        halachotPager.OffscreenPageLimit = 2;
        halachotPager.SetCurrentItem(1, true);
        // Bind the tabs to the ViewPager
        tabs = view.FindViewById<PagerSlidingTabStrip>(Resource.Id.halachotTabs);

        tabs.SetViewPager(halachotPager);

        return view;

    }

Is this what you meant? If so, it doesn't help. :(

Reply
Amitai Rosenberg
  • Forum posts: 27

Jun 5, 2016, 7:44:49 PM via Website

I thought maybe it's a problem with my layout, so I'm posting my xml code:

Main:
Main

HalachaSection (for HalachaFragment):
HalachaSection

I know my layout is a bit messed up. If you could help me clean it a bit and maybe rearrange it, maybe that will help with the performance (also to solve the weird issue I have with the shadows which is why I need to change the Support Action Bar Elevation each time).

Thanks!

Reply
damponting44
  • Forum posts: 70

Oct 6, 2016, 2:28:12 PM via Website

Much appreciated. I figured out how to minimize the slack by equipment speeding up, evacuating movement and pointless code. Albeit notwithstanding when I don't put any picture in the second part (the one with the tabs), there is a little slack that doesn't happen when I tap on the others or when I open the same piece a second time.

Is there an approach to introduce the piece before opening it, so that once it is opened it will be stacked and won't slack?

Then again whatever other recommendations?

Much appreciated!

Reply
Cesar Romero
  • Forum posts: 1

Nov 14, 2019, 6:19:26 PM via Website

Hi everyone,

I have read all the comments in this forum because I had the same trouble than Amitai Rosenberg, and I know this thread is already old.

I have follow all the steps descripted here but its not resolved until I had take off all the images that had much KB and MB from folder "drawable" and only it stay that I used and Yeah!! Its works, the app work fluid.
Well that is my experience.
Greetings

— modified on Nov 14, 2019, 6:21:16 PM

Reply