简体   繁体   中英

Custom Android TabHost Slow Fragments

I use ActionbarSherlock and SlidingMenu.

My MainActivity does not access a DB and no Parsing of what ever. Everything is static.

Tabs are generated dynamicly depending on the "Section" you choose from the SlidingMenu. After 2 click the app becomes awefully slow.

Below is my main view.

    <TabHost
        android:id="@android:id/tabhost"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical" >

            <TabWidget
                android:id="@android:id/tabs"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal" />

            <FrameLayout
                android:id="@+id/content_frame"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#0000FF" >
            </FrameLayout>

            <FrameLayout
                android:id="@android:id/tabcontent"
                android:layout_width="0dp"
                android:layout_height="0dp" >

            </FrameLayout>

        </LinearLayout>
    </TabHost>

</LinearLayout>

The code used to manage Tabhost & Fragments :

public void selectPage(MenuPageItem page, Page subNavigationPage) {
    if (page == null || subNavigationPage == null
            || (page.equals(selectedPage) && subNavigationPage.equals(selectedSubNavigation))) {
        return;
    }
    Log.d(TAG, "Show the page: " + page.getTitle() + " / subNavigationPage: " + subNavigationPage.getTitle());

    boolean needUpdateTabUI = !(page.equals(selectedPage));
    selectedPage = page;
    selectedSubNavigation = subNavigationPage;

    // 1) Manage tabHost
    if (needUpdateTabUI) {
        Log.d(TAG, "need to update tab layout");
        updatePageTabUI();
    }
    // Change selected tab
    mTabHost.setCurrentTabByTag(selectedSubNavigation.getTitle());

    // 2) Change Contentfragment
    Log.d(TAG, "update fragment");
    // TODO: check the current fragment is not already the good one and just
    // call its updateData method
    updatePageFragment();

    // Close the sliding menu if opened
    if (getSlidingMenu().isShown()) {
        Handler h = new Handler();

        h.postDelayed(new Runnable() {
            public void run() {
                getSlidingMenu().showContent();
            }
        }, 50);
    }
}

private void updatePageTabUI() {
    if (selectedPage.getPages().size() > 1) {
        // More than one sub navigation -> show the tab host
        // mTabHost.setVisibility(View.VISIBLE);
        mTabHost.setup();
        mTabHost.clearAllTabs();
        int i = 0;
        for (final Page subnav : selectedPage.getPages()) {
            Log.d(TAG, "add tab tag=" + subnav.getTitle() + " title=" + subnav.getTitle());
            mTabHost.addTab(mTabHost.newTabSpec(subnav.getTitle()).setIndicator(subnav.getTitle())
                    .setContent(new EmptyTabFactory()));
            mTabHost.getTabWidget().getChildAt(i).setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    selectPage(selectedPage, subnav);
                }
            });
            i++;
        }

    } else {
        // Only one sub navigation -> hide the tab host
        // mTabHost.setVisibility(View.GONE);
        mTabHost.setup();
        mTabHost.clearAllTabs();
    }
    mTabHost.requestLayout();
    mTabHost.invalidate();
}

private void updatePageFragment() {
    try {
        PageFragment fragContent = (PageFragment) selectedSubNavigation.getFragmentClass().newInstance();
        fragContent.setSubNavigationPage(selectedSubNavigation);
        FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
        fragmentTransaction.replace(R.id.content_frame, fragContent);
        fragmentTransaction.commit();
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
}

You keep your entire work on UIThread and therefore you eventually stumble upon slow response (For example this is one of the reasons why it is forbidden on latest Android OS to do networking on UI thread). Try changing your concept a little bit and do your tab creation in background on different thread. Or at least lock UI and show wait dialog when you do your work in order for user to have proper UI experience.

Hope this helps and enjoy your work.

@Marko answer isn't bad, I just happen to found the 'real' culprit. I will be exploring the path Marko pointed out.

What I found is that inside SlidingMenu adapter we had a ViewBadger (lib) and it wasn't re-used properly, creating views each time we change fragment.

BadgeView b = new BadgeView(getActivity(), holder.icon);
holder.badger = b;
convertView.setTag(holder);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM