preface

In fact, OVER the years of development, I still know little about fragments. Here I would like to sort out how to systematically master the use of fragments in daily work

Advantages of fragments

1. If there are many simple pages and a whole set of jump logic before and after them, using multiple activities is too cumbersome. If there are multiple layouts in a single Activity to show and hide codes, it is not easy to read and coupling is too strong. Light switch. 2. Fragment is actually a control in Acitivty, but it has a complete life cycle, so we have plenty of space to operate.

Fragments using

See article Fragment for early full usage parsing

Tips this series of articles is actually a good comb of the daily use of fragments, but the article is too old, so I temporarily use it as a review, and then I still need to analyze the latest source code. I will briefly list the core points of this series of articles to prepare for the future

Pay attention to the Fragment life cycle, where the view is initialized, and passing parameters. FragmentManager (FragmentManager); FragmentManager (FragmentManager); 5. Pay attention to the difference between Add and show, especially with replace. This intuitive feeling is that add cannot be used with replace when switching Fragments. FragmentTrasncation is used in fragments. It is very important to understand the concept of FragmentTrasncation in fragments. 8. 9. Replace is to empty the view, and it will be redrawn if it is displayed again. How do we use replace to rollback and still ensure the state after the user input?

On the continuation of the problem, in the reference article one by one to give the answer, need readers to understand seriously

Refer to the secondWebsite on

Use of same-level Fragment switching

Used in the project

package org.cy.uilibrary;

import android.util.Log;

import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;


/**
 * 
 */
public class FragmentUtils {

    private static final String TAG = "FragmentUtils";

    public static void replaceFragment(FragmentManager manager, Fragment fragment,
                                       boolean addToBackStack) {
        replaceFragment(manager, fragment, addToBackStack, R.id.fragment_container, false,
                R.anim.slide_in_left, R.anim.slide_out_right, R.anim.pop_enter, R.anim.pop_exit);
    }

    public static void showFragmentAllowingStateLoss(FragmentManager manager, Fragment fragment,
                                                     boolean addToBackStack) {
        replaceFragment(manager, fragment, addToBackStack, R.id.fragment_container, true,
                R.anim.slide_in_left, R.anim.slide_out_right, R.anim.pop_enter, R.anim.pop_exit);
    }

    public static void showFragmentWithOutAnimation(FragmentManager manager, Fragment fragment,
                                                    boolean addToBackStack) {
        replaceFragment(manager, fragment, addToBackStack, R.id.fragment_container, false);
    }

    public static void showFragmentWithOutAnimation(FragmentManager manager, Fragment fragment,
                                                    boolean addToBackStack, boolean commitStateLoss) {
        replaceFragment(manager, fragment, addToBackStack, R.id.fragment_container, commitStateLoss);
    }

    public static void showFragmentWithCustomAnimation(FragmentManager manager, Fragment fragment,
                                                       boolean addToBackStack, int... animations) {
        replaceFragment(manager, fragment, addToBackStack, R.id.fragment_container, false, animations);
    }

    /**
     * 每次返回执行生命周期
     * @param manager        fragment的事物管理者
     * @param fragment       切换的fragment
     * @param addToBackStack 是否加入回退栈
     * @param resId          fragment的 container
     * @param animations     fragment切换动画(请按照此顺序添加动画:enter->exit->popEnter->popExit)
     */
    private static void replaceFragment(FragmentManager manager, Fragment fragment,
                                        boolean addToBackStack, int resId, boolean commitStateLoss, int... animations) {
        if (manager == null) {
            return;
        }
        FragmentTransaction ft = manager.beginTransaction();
        if (animations.length > 0) {
            ft.setCustomAnimations(animations[0], animations[1], animations[2], animations[3]);
        }
        String fragmentName = fragment.getClass().getName();
        Log.d("showFragment", "fragmentName = " + fragmentName);
        ft.replace(resId, fragment, fragmentName);

        if (addToBackStack) {
            ft.addToBackStack(fragmentName);
        }

        try {
            if (commitStateLoss) {
                ft.commitAllowingStateLoss();
            } else {
                ft.commit();
            }
        } catch (Exception e) {
            Log.e(TAG, "Exception:" + e.getMessage());
        }

    }


    /***
     * 不执行生命周期
     * @param manager
     * @param fragment
     * @param addToBackStack
     * @param resId
     * @param commitStateLoss
     * @param animations
     */
    private static void addFragment(FragmentManager manager, Fragment fragment,
                                    boolean addToBackStack, int resId, boolean commitStateLoss, int... animations) {
        FragmentTransaction ft = manager.beginTransaction();
        if (animations.length > 0) {
            ft.setCustomAnimations(animations[0], animations[1], animations[2], animations[3]);
        }
        String fragmentName = fragment.getClass().getName();
        ft.add(resId, fragment, fragmentName);
        if (addToBackStack) {
            ft.addToBackStack(fragmentName);
        }
        try {
            if (commitStateLoss) {
                ft.commitAllowingStateLoss();
            } else {
                ft.commit();
            }
        } catch (Exception e) {
            Log.e(TAG, "Exception:" + e.getMessage());
        }
    }


    public static void addFragment(FragmentManager manager, Fragment fragment,
                                   boolean addToBackStack) {
        addFragment(manager, fragment, addToBackStack, R.id.fragment_container, false,
                R.anim.slide_in_left, R.anim.slide_out_right, R.anim.pop_enter, R.anim.pop_exit);
    }

    public static void addFragmentWithOutAnimation(FragmentManager manager, Fragment fragment,
                                                   boolean addToBackStack) {
        addFragment(manager, fragment, addToBackStack, R.id.fragment_container, false);
    }

    public static void addFragmentWithCustomAnimation(FragmentManager manager, Fragment fragment,
                                                      boolean addToBackStack, int... animations) {
        addFragment(manager, fragment, addToBackStack, R.id.fragment_container, false, animations);
    }

    public static void addFragmentWithCustomAnimation(FragmentManager manager, Fragment fragment,
                                                      boolean addToBackStack, boolean commitStateLoss) {
        addFragment(manager, fragment, addToBackStack, R.id.fragment_container, commitStateLoss);
    }


    public static Fragment getCurrentFragment(FragmentManager manager) {
        return manager.findFragmentById(R.id.fragment_container);
    }

    public static String getCurrentFragmentTag(FragmentManager manager) {
        int backStackEntryCount = manager.getBackStackEntryCount();
        if (backStackEntryCount <= 0) {
            return null;
        }
        String fragmentTag = manager.getBackStackEntryAt(
                backStackEntryCount - 1).getName();
        return fragmentTag;
    }

    /**
     * 清除某个Fragment以及其以上的所有Fragment(这里需要注意的是会清除fragmentClass本身)
     *
     * @param fragmentClass 某个fragment class
     */
    public static void clearFragment(FragmentManager manager, Class fragmentClass) {
        int num = manager.getBackStackEntryCount();
        for (int i = 0; i < num; i++) {
            FragmentManager.BackStackEntry stackEntry = manager.getBackStackEntryAt(i);
            if (stackEntry.getName().equals(fragmentClass.getName())) {
                manager.popBackStack(stackEntry.getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
                break;
            }
        }
    }

    /**
     * 清除fragment栈除了最初的其他所有fragment
     */
    public static void clearFragmentAll(FragmentManager manager) {
        if (manager.getBackStackEntryCount() > 0) {
            FragmentManager.BackStackEntry first = manager.getBackStackEntryAt(0);
            manager.popBackStack(first.getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
        }
    }

    public static boolean containFragment(FragmentManager manager, Class fragmentClass) {
        int num = manager.getBackStackEntryCount();
        for (int i = 0; i < num; i++) {
            FragmentManager.BackStackEntry stackEntry = manager.getBackStackEntryAt(i);
            if (stackEntry.getName().equals(fragmentClass.getName())) {
                return true;
            }
        }
        return false;
    }


    public interface OnBackPressedListener {

        boolean onBackPressed();
    }
}

Copy the code

Do STH for sb

1. Use of the new Fragment

2, Fragment source code analysis