0

1 つまたは 2 つのページ (ユーザー プロファイルによる) を持つダッシュボードを持つアプリケーションがあります。

アプリケーションの初回起動時には 3 つのボタンしか表示されませんが、情報が到着すると、さらに 3 つのボタン (合計 6 つ) を追加できます。これらのボタンには特定の順序があり、それを維持する必要があります。

  • ボタン 1 は必須で、最初に配置する必要があります。
  • ボタン 2 は必須で、2 番目に配置する必要があります。
  • ボタン 6 は必須であり、最後にする必要があります (3、4、5、または 6 がある場合)
  • ボタン 3 ~ 5 は必須ではありませんが、番号順に表示する必要があります。

この効果を得るために、フラグメントが追加されるプレースホルダーがいくつかあります。新しいボタン (ボタン 3 から 5) が到着するたびに、1 つ前に移動する Button_6 の古い場所に入ります。

UI と動作が複雑なため、各ボタンはフラグメントです。

アプリケーションは、縦向きと横向きで、縦向きに 4 つのボタン、横向きに 3 つのボタンがあります。アプリケーションが回転するたびに、アクティビティは refreshDashboard メソッドを呼び出して UI を再描画します。

コード:

public class DashboardBuilder
{
    private final static String TAG_BUTTON_1 = "BUTTON_1";
    private final static String TAG_BUTTON_2 = "BUTTON_2";
    private final static String TAG_BUTTON_3 = "BUTTON_3";
    private final static String TAG_BUTTON_4 = "BUTTON_4";
    private final static String TAG_BUTTON_5 = "BUTTON_5";
    private final static String TAG_BUTTON_6 = "BUTTON_6";

    private int width = 0;
    private int height = 0;
    private int pages = 0;

    private int buttonsPerPage = 4;
    private int orientation = Configuration.ORIENTATION_PORTRAIT;

    public final String TAG = getClass().getSimpleName();

    public DashboardBuilder(DashboardPaginationActivity dashboard)
    {      
            FragmentManager.enableDebugLogging(false);   
    }

    //This is called each time there is a rotation. 
    public void rebuildDashboard(DashboardPaginationActivity dashboard, int orientation)
    {
        switch (orientation)
        {
            case Configuration.ORIENTATION_LANDSCAPE:
            case Configuration.ORIENTATION_SQUARE:
                buttonsPerPage = 3;
                break;
            default:
                buttonsPerPage = 4;
                break;
        }

        this.width = dashboard.getWidth();
        this.height = dashboard.getHeight();

        // Orientation changed
        if (this.orientation != orientation)
        {
            this.orientation = orientation;
            pages = 0;
        }
        rebuildDashboard(dashboard);
    }

    private synchronized void rebuildDashboard(DashboardPaginationActivity dashboard)
    {
        final Application application = (Application) dashboard.getApplication();
        final ArrayList<FragmentReference> fragmentsReferences = application.getFragmentsReferences();

        if (fragmentsReferences.size() == 0)
        {
            try
            {
                final String[] tags = new String[] { TAG_BUTTON_1, TAG_BUTTON_2, TAG_BUTTON_3, TAG_BUTTON_4, TAG_BUTTON_5, TAG_BUTTON_6 };
                for (String tag : tags)
                {
                    Fragment fragment = dashboard.getSupportFragmentManager().findFragmentByTag(tag);
                    if (fragment != null)
                    {
                        LOG.debug(LOG.TAG_ADAPTER, this, "rebuildDashboard : delete tag -> " + tag, null);
                        fragmentsReferences.add(new FragmentReference(tag, fragment.getId()));
                    }
                }

                final ViewGroup pages = (ViewGroup) dashboard.findViewById(R.id.dashboard_pages);
                pages.removeAllViews();

                final ViewGroup pagination = (ViewGroup) dashboard.findViewById(R.id.pagination);
                pagination.removeAllViews();
            }
            catch (Exception e)
            {
            }

            // Definitely a first run
            if (fragmentsReferences.size() == 0)
            {
                // add mandatory buttons + refresh layout
                fragmentsReferences.add(new FragmentReference(TAG_BUTTON_1, -1));
                fragmentsReferences.add(new FragmentReference(TAG_BUTTON_2, -1));
                fragmentsReferences.add(new FragmentReference(TAG_BUTTON_6, -1));
            }

            refreshDashboard(dashboard, false);
        }
        else
        {
            // refresh layout
            refreshDashboard(dashboard, true);
        }

    }

    public void refreshDashboard(DashboardPaginationActivity dashboard, boolean exitOnNewButton)
    {
        final Application application = (Application) dashboard.getApplication();
        final ArrayList<FragmentReference> fragmentsReferences = application.getFragmentsReferences();

        int buttonsCounter = fragmentsReferences.size();

        int pagesCounter = (buttonsCounter / (buttonsPerPage + 1)) + 1;
        for (int i = pages; i < pagesCounter; i++)
        {
            final View pageInflator = createPage(dashboard, i);
            if (pageInflator != null && i > 0)
            {
                swapIDs(i, pageInflator);
            }
        }

        final FragmentManager manager = dashboard.getSupportFragmentManager();
        final FragmentTransaction transaction = manager.beginTransaction();
        for (int i = fragmentsReferences.size() - 1; i >= 0; i--)
        {
            Fragment fragment = null;
            if (TAG_BUTTON_1.equalsIgnoreCase(fragmentsReferences.get(i).getTag()))
            {
                fragment = manager.findFragmentByTag(TAG_BUTTON_1);
                if (fragment != null)
                {
                    transaction.remove(fragment);
                }
                ButtonOneFragment button = new ButtonOneFragment();
                button.setRetainInstance(false);
                transaction.replace(getPlaceHolder(i), button, TAG_BUTTON_1);
                transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);

                fragmentsReferences.get(i).setPlaceHolder(getPlaceHolder(i));
            }
            else if (TAG_BUTTON_2.equalsIgnoreCase(fragmentsReferences.get(i).getTag()))
            {
                fragment = manager.findFragmentByTag(TAG_BUTTON_2);
                if (fragment != null)
                {
                    transaction.remove(fragment);
                }
                ButtonTwoFragment button = new ButtonTwoFragment();
                button.setRetainInstance(false);
                transaction.replace(getPlaceHolder(i), button, TAG_BUTTON_2);
                transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);

                fragmentsReferences.get(i).setPlaceHolder(getPlaceHolder(i));

            }
            else if (TAG_BUTTON_3.equalsIgnoreCase(fragmentsReferences.get(i).getTag()))
            {

                fragment = manager.findFragmentByTag(TAG_BUTTON_3);
                if (fragment != null)
                {
                    transaction.remove(fragment);
                }
                ButtonThreeFragment button = new ButtonThreeFragment();
                button.setRetainInstance(false);
                transaction.replace(getPlaceHolder(i), button, TAG_BUTTON_3);
                transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
                fragmentsReferences.get(i).setPlaceHolder(getPlaceHolder(i));

            }
            else if (TAG_BUTTON_4.equalsIgnoreCase(fragmentsReferences.get(i).getTag()))
            {
                fragment = manager.findFragmentByTag(TAG_BUTTON_4);
                if (fragment != null)
                {
                    transaction.remove(fragment);
                }
                ButtonFourFragment button = new ButtonFourFragment();
                button.setRetainInstance(false);
                transaction.replace(getPlaceHolder(i), button, TAG_BUTTON_4);
                transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
                fragmentsReferences.get(i).setPlaceHolder(getPlaceHolder(i));
            }
            else if (TAG_BUTTON_5.equalsIgnoreCase(fragmentsReferences.get(i).getTag()))
            {
                fragment = manager.findFragmentByTag(TAG_BUTTON_5);
                if (fragment != null)
                {
                    transaction.remove(fragment);
                }
                ButtonFiveFragment button = new ButtonFiveFragment();
                button.setRetainInstance(false);
                transaction.replace(getPlaceHolder(i), button, TAG_BUTTON_5);
                transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
                fragmentsReferences.get(i).setPlaceHolder(getPlaceHolder(i));
            }
            else if (TAG_BUTTON_6.equalsIgnoreCase(fragmentsReferences.get(i).getTag()))
            {
                fragment = manager.findFragmentByTag(TAG_BUTTON_6);
                if (fragment != null)
                {
                    transaction.remove(fragment);
                }
                ButtonSixFragment button = new ButtonSixFragment();
                button.setRetainInstance(false);
                transaction.replace(getPlaceHolder(i), button, TAG_BUTTON_6);
                transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
                fragmentsReferences.get(i).setPlaceHolder(getPlaceHolder(i));
            }

            if (exitOnNewButton)
            {
                // on first new button found
                if (fragmentsReferences.get(i).getPlaceHolder() < 0) break;
            }
        }

        buttonsCounter = fragmentsReferences.size();
        pagesCounter = (buttonsCounter / (buttonsPerPage + 1)) + 1;

        for (int i = pages; i > pagesCounter; i--)
        {
            // scroll to first if removing
            dashboard.changePage(0);
            removePage(dashboard, i - 1);
        }

        pages = pagesCounter;
        dashboard.setTotalScreens(pages);

        try
        {
            // we suspect that this is only required when a remove happens
            // keep it here in all cases to be on the safe site...
            transaction.commit();
            manager.executePendingTransactions();
        }
        catch (Exception e)
        {
            // ignore exception
            LOG.error(LOG.TAG_FRAGMENT, this, "refreshDashboard", e.getMessage());
            // e.printStackTrace();
        }
    }

    private View createPage(DashboardPaginationActivity dashboard, int index)
    {
        final View pageHolder = dashboard.getLayoutInflater().inflate(R.layout.dashboard_page, null);
        pageHolder.setLayoutParams(new LinearLayout.LayoutParams(getHorizontalScrollWidth(dashboard), getHorizontalScrollHeight(dashboard)));

        View existingView = null;

        final View page = pageHolder.findViewById(R.id.page);
        switch (index)
        {
            case 0:
                if (dashboard.findViewById(R.id.page1) == null)
                {
                    page.setId(R.id.page1);
                }
                existingView = dashboard.findViewById(R.id.page1);
                break;
            case 1:
                if (dashboard.findViewById(R.id.page2) == null)
                {
                    page.setId(R.id.page2);
                }
                existingView = dashboard.findViewById(R.id.page2);
                break;
            default:
                break;
        }

        if (existingView != null)
        {
            return null;
        }

        // add page holder to dashboard

        ViewGroup pages = ((ViewGroup) dashboard.findViewById(R.id.dashboard_pages));
        pages.addView(pageHolder);

        return pageHolder;
    }

    private void removePage(DashboardPaginationActivity dashboard, int index)
    {
        if (((ViewGroup) dashboard.findViewById(R.id.dashboard_pages)).getChildCount() > index)
        {
            ((ViewGroup) dashboard.findViewById(R.id.dashboard_pages)).removeViewAt(index);
        }
    }

          private void swapIDs(int index, View pageInflator)
    {
        if (orientation == Configuration.ORIENTATION_LANDSCAPE || orientation == Configuration.ORIENTATION_SQUARE)
        {
            swapLandscapeIDs(index, pageInflator);
        }
        else
        {
            swapPortraitIDs(index, pageInflator);
        }
    }

    private Integer getFragmentPlaceHolder(DashboardPaginationActivity dashboard, String tag)
    {
        if (tag != null)
        {
            final Application application = (Application) dashboard.getApplication();
            final ArrayList<FragmentReference> fragmentsReferences = application.getFragmentsReferences();

            for (int i = 0; i < fragmentsReferences.size(); i++)
            {
                final String fragmentTag = fragmentsReferences.get(i).getTag();
                if (tag.equalsIgnoreCase(fragmentTag))
                {
                    return fragmentsReferences.get(i).getPlaceHolder();
                }
            }
        }
        return null;
    }

    private Integer addFragmentReference(DashboardPaginationActivity dashboard, String tag)
    {
        int index = 0;
        if (tag != null)
        {
            final Application application = (Application) dashboard.getApplication();
            final ArrayList<FragmentReference> fragmentsReferences = application.getFragmentsReferences();

            if (tag.equalsIgnoreCase(TAG_BUTTON_1))
            {
                fragmentsReferences.add(0, new FragmentReference(TAG_BUTTON_1, -1));
                index = 0;
            }

            if (tag.equalsIgnoreCase(TAG_BUTTON_2))
            {
                fragmentsReferences.add(1, new FragmentReference(TAG_BUTTON_2, -1));
                index = 1;
            }

            if (tag.equalsIgnoreCase(TAG_BUTTON_3))
            {
                fragmentsReferences.add(2, new FragmentReference(TAG_BUTTON_3, -1));
                index = 2;
            }
            else if (tag.equalsIgnoreCase(TAG_BUTTON_4))
            {
                if (TAG_BUTTON_3.equalsIgnoreCase(fragmentsReferences.get(2).getTag()))
                {
                    fragmentsReferences.add(3, new FragmentReference(TAG_BUTTON_4, -1));
                    index = 3;
                }
                else
                {
                    fragmentsReferences.add(2, new FragmentReference(TAG_BUTTON_4, -1));
                    index = 2;
                }
            }
            else if (tag.equalsIgnoreCase(TAG_BUTTON_5))
            {
                if (fragmentsReferences.size() == 5 && TAG_BUTTON_4.equalsIgnoreCase(fragmentsReferences.get(3).getTag()))
                {
                    fragmentsReferences.add(4, new FragmentReference(TAG_BUTTON_5, -1));
                    index = 4;
                }
                else if (fragmentsReferences.size() == 4 && (TAG_BUTTON_3.equalsIgnoreCase(fragmentsReferences.get(2).getTag()) || TAG_BUTTON_4.equalsIgnoreCase(fragmentsReferences.get(2).getTag())))
                {
                    fragmentsReferences.add(3, new FragmentReference(TAG_BUTTON_5, -1));
                    index = 3;
                }
                else
                {
                    fragmentsReferences.add(2, new FragmentReference(TAG_BUTTON_5, -1));
                    index = 2;
                }
            }
        }
        return index;
    }

    private void removeFragmentReference(DashboardPaginationActivity dashboard, String tag)
    {
        if (tag != null)
        {
            final Application application = (Application) dashboard.getApplication();
            final ArrayList<FragmentReference> fragmentsReferences = application.getFragmentsReferences();

            // start at 2 means that button 1 and 2 will never be removed
            for (int i = 0; i < fragmentsReferences.size(); i++)
            {
                final String fragmentTag = fragmentsReferences.get(i).getTag();
                if (tag.equalsIgnoreCase(fragmentTag))
                {
                    fragmentsReferences.remove(i);
                    break;
                }
            }

            final FragmentManager manager = dashboard.getSupportFragmentManager();
            final Fragment fragment = manager.findFragmentByTag(tag);
            if (fragment != null)
            {
                final FragmentTransaction transaction = manager.beginTransaction();

                // remove store references and other resources
                // ((ButtonFragment) fragment).cleanup();

                transaction.remove(fragment);
                transaction.commit();

                try
                {
                    // we suspect that this is only required when a remove happens
                    // keep it here in all cases to be on the safe site...
                    manager.executePendingTransactions();
                }
                catch (Exception e)
                {
                    // ignore exception
                    LOG.debug(LOG.TAG_FRAGMENT, this, "removeFragmentReference", null);
                }
            }
        }
    }

    public boolean buttonExists(DashboardPaginationActivity dashboard, String tag)
    {
        if (tag == null) return false;

        final Application application = (Application) dashboard.getApplication();
        final ArrayList<FragmentReference> fragmentsReferences = application.getFragmentsReferences();

        for (int i = 0; i < fragmentsReferences.size(); i++)
        {
            final String fragmentTag = fragmentsReferences.get(i).getTag();
            if (tag.equalsIgnoreCase(fragmentTag))
            {
                return true;
            }
        }
        return false;
    }

    private int getPlaceHolder(int index)
    {
        switch (index)
        {
            case 0:
                return R.id.placeHolder01;
            case 1:
                return R.id.placeHolder02;
            case 2:
                return R.id.placeHolder03;
            case 3:
                return R.id.placeHolder04;
            case 4:
                return R.id.placeHolder05;
            case 5:
                return R.id.placeHolder06;
            case 6:
                return R.id.placeHolder07;
            case 7:
                return R.id.placeHolder08;
            case 8:
                return R.id.placeHolder09;
            case 9:
                return R.id.placeHolder10;
            case 10:
                return R.id.placeHolder11;
            case 11:
                return R.id.placeHolder12;
            default:
                return -1;
        }
    }

    private void swapPortraitIDs(int index, View pageInflated)
    {
        switch (index)
        {
            case 1:
                pageInflated.findViewById(R.id.placeHolder01).setId(R.id.placeHolder05);
                pageInflated.findViewById(R.id.placeHolder02).setId(R.id.placeHolder06);
                pageInflated.findViewById(R.id.placeHolder03).setId(R.id.placeHolder07);
                pageInflated.findViewById(R.id.placeHolder04).setId(R.id.placeHolder08);
                break;
            case 2:
                pageInflated.findViewById(R.id.placeHolder01).setId(R.id.placeHolder09);
                pageInflated.findViewById(R.id.placeHolder02).setId(R.id.placeHolder10);
                pageInflated.findViewById(R.id.placeHolder03).setId(R.id.placeHolder11);
                pageInflated.findViewById(R.id.placeHolder04).setId(R.id.placeHolder12);
                break;
            default:
                LOG.error(LOG.TAG_ACTIVITY, activity, "swapPortraitIDs", "Invalid page number: " + index);
                break;
        }

    }

    private void swapLandscapeIDs(int index, View pageInflated)
    {
        switch (index)
        {
            case 1:
                pageInflated.findViewById(R.id.placeHolder01).setId(R.id.placeHolder04);
                pageInflated.findViewById(R.id.placeHolder02).setId(R.id.placeHolder05);
                pageInflated.findViewById(R.id.placeHolder03).setId(R.id.placeHolder06);
                break;
            case 2:
                pageInflated.findViewById(R.id.placeHolder01).setId(R.id.placeHolder07);
                pageInflated.findViewById(R.id.placeHolder02).setId(R.id.placeHolder08);
                pageInflated.findViewById(R.id.placeHolder03).setId(R.id.placeHolder09);
                break;
            default:
                LOG.error(LOG.TAG_ACTIVITY, activity, "swapLandscapeIDs", "Invalid page number: " + index);
                break;
        }
    }


    public int[] getPagesIds(AbstractActivity activity)
    {
        switch (pages)
        {
            case 1:
                return new int[] { R.id.page1 };
            case 2:
                return new int[] { R.id.page1, R.id.page2 };
            default:
                LOG.error(LOG.TAG_ACTIVITY, activity, "getPagesIds", "Invalid page number: " + pages);
                return new int[0];
        }
    }

}

manager.executePendingTransactions(); を採用する必要がありました。try catch を使用すると、「ランダムに」 java.lang.IllegalStateException: Recursive entry to executePendingTransactions がスローされるため、短い時間で多くのローテーションが発生します。

これは Fragments Manager の非同期性によるものだと思います。

私はそれらのtry catchesの問題を「解決」しました..それでも、それを解決するためのより正しい方法やアドバイスがあるかどうかを知りたいです。

Try キャッチ前の StackTrace:

 

19:04:47.402 E/AndroidRuntime( 1352): FATAL EXCEPTION: main 
 19:04:47.402 E/AndroidRuntime( 1352): java.lang.IllegalStateException: Recursive entry to executePendingTransactions 
 19:04:47.402 E/AndroidRuntime( 1352): at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1388) 
 19:04:47.402 E/AndroidRuntime( 1352): at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:420) 
 19:04:47.402 E/AndroidRuntime( 1352): at android.os.Handler.handleCallback(Handler.java:587) 
 19:04:47.402 E/AndroidRuntime( 1352): at android.os.Handler.dispatchMessage(Handler.java:92) 
 19:04:47.402 E/AndroidRuntime( 1352): at android.os.Looper.loop(Looper.java:123) 
 19:04:47.402 E/AndroidRuntime( 1352): at android.app.ActivityThread.main(ActivityThread.java:3683) 
 19:04:47.402 E/AndroidRuntime( 1352): at java.lang.reflect.Method.invokeNative(Native Method) 
 19:04:47.402 E/AndroidRuntime( 1352): at java.lang.reflect.Method.invoke(Method.java:507) 
 19:04:47.402 E/AndroidRuntime( 1352): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839) 
 19:04:47.402 E/AndroidRuntime( 1352): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597) 
 19:04:47.402 E/AndroidRuntime( 1352): at dalvik.system.NativeStart.main(Native Method) 
 19:04:47.406 W/ActivityManager(  107):   Force finishing activity com.dashboard.tests/.activity.MainActivity
 19:04:47.402 E/AndroidRuntime( 1352): FATAL EXCEPTION: main 
 19:04:47.402 E/AndroidRuntime( 1352): java.lang.IllegalStateException: Recursive entry to executePendingTransactions 
 19:04:47.402 E/AndroidRuntime( 1352): at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1388) 
 19:04:47.402 E/AndroidRuntime( 1352): at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:420)

Android デベロッパー オフィス アワー (http://www.google.com/moderator/#15/e=1ac28e&t=1ac28e.51) でリクエストされたとおり、Android クルーが確認できるコードを以下に示します。

ありがとう

Ps: 長いコード スニペットで申し訳ありません。

4

0 に答える 0