Make writing a habit together! This is the fourth day of my participation in the “Gold Digging Day New Plan · April More text Challenge”. Click here for more details.

This article focuses on how to quickly implement Activity lifecycle monitoring and its application in official Lifecycle, third-party library Glide, and PermissionX

1.ActivityLifecycle monitoring

  • FragmentimplementationActivityLifecycle monitoring

As we all know, life cycle distribution in fragments relies on activities, so to listen for an Activity’s life cycle we simply add an empty Fragment:

class TestFragment(): Fragment() {
    override fun onCreate(savedInstanceState: Bundle?). {
        super.onCreate(savedInstanceState)
       
    }

    override fun onDestroy(a) {
        super.onDestroy()
    }
}

// Get the activity first
activity.supportFragmentManager.beginTransaction().apply {
    add(TestFragment(), "TestFragment").commit()
}
Copy the code

This allows us to listen for the Activity’s lifecycle in methods like onCreate, onDestory, etc., and execute the related logic

PS: Through FragmentManager FragmentTransaction add fragments, the add method of the second parameter tag don't direct incoming TestFragment: : class. Java. SimpleName, Once the fragments are mixed up, the tags of different fragments added may be the same, affecting the subsequent use

  • registerActivityLifecycleCallbacksimplementationActivityLifecycle listening (API >=29)

This method is provided by SDK>=29.

// Callback collection
private final ArrayList<Application.ActivityLifecycleCallbacks> mActivityLifecycleCallbacks =
        new ArrayList<Application.ActivityLifecycleCallbacks>();

// Add a callback that listens for the Activity lifecycle
public void registerActivityLifecycleCallbacks(
        @NonNull Application.ActivityLifecycleCallbacks callback) {
    synchronized(mActivityLifecycleCallbacks) { mActivityLifecycleCallbacks.add(callback); }}Copy the code

Where see mActivityLifecycleCallbacks call, here are with onStart life cycle of Activity, for instance:

private Object[] collectActivityLifecycleCallbacks() {
    Object[] callbacks = null;
    synchronized (mActivityLifecycleCallbacks) {
        if (mActivityLifecycleCallbacks.size() > 0) { callbacks = mActivityLifecycleCallbacks.toArray(); }}return callbacks;
}

    private void dispatchActivityStarted() {
        getApplication().dispatchActivityStarted(this);
        / / get mActivityLifecycleCallback callback array
        Object[] callbacks = collectActivityLifecycleCallbacks();
        if(callbacks ! =null) {
            for (int i = 0; i < callbacks.length; i++) {
            // Distribute the start lifecycle
                ((Application.ActivityLifecycleCallbacks) callbacks[i]).onActivityStarted(this); }}}protected void onStart() {
    ...
    // Call dispatchActivityStarted to implement lifecycle distributiondispatchActivityStarted(); . }Copy the code

In the Activity of the onStart call dispatchActivityStarted distribute () method of life cycle, the latter first calls the collectActivityLifecycleCallbacks add () to obtain the life cycle of a back to assemble merge into an array, It then iterates through the onStart life cycle of the distribution Activity

2. Case 1: Lifecycle application practice of the official library

Lifecycle is also implemented by the official library through a combination of the above two methods:

public static void injectIfNeededIn(Activity activity) {
    if (Build.VERSION.SDK_INT >= 29) {
        LifecycleCallbacks.registerIn(activity);
    }
    // Compatible with older versions
    android.app.FragmentManager manager = activity.getFragmentManager();
    if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
        manager.beginTransaction().add(newReportFragment(), REPORT_FRAGMENT_TAG).commit(); manager.executePendingTransactions(); }}static void registerIn(Activity activity) {
    activity.registerActivityLifecycleCallbacks(new LifecycleCallbacks());
}

Copy the code

Can see from the source, the SDK > = 29 use registerActivityLifecycleCallbacks listening life cycle, less than 29 just by adding ReportFragment listens to the Activity.

Note that even SDK >=29 still adds ReportFragment logic, this is mainly for compatibility with older versions

3. Case 2: Glide Library application practice

Glide defines a named SupportRequestManagerFragment, inherited from fragments:

public class SupportRequestManagerFragment extends Fragment {
    private final ActivityFragmentLifecycle lifecycle;
    
    @Override
    public void onStart(a) {
      lifecycle.onStart();
    }

    @Override
    public void onStop(a) {
      lifecycle.onStop();
    }

    @Override
    public void onDestroy(a) { lifecycle.onDestroy(); }}Copy the code

Through getSupportRequestManagerFragment () added to the Activity

@NonNull
private SupportRequestManagerFragment getSupportRequestManagerFragment(
    @NonNull final FragmentManager fm, @Nullable Fragment parentHint) {
  SupportRequestManagerFragment current = pendingSupportRequestManagerFragments.get(fm);
  if (current == null) {
    current = (SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
    if (current == null) {
      current = newSupportRequestManagerFragment(); fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss(); }}return current;
}
Copy the code

It is well known that using Glide’s with function requires passing in a Context, be it an Activity, Fragment, etc.

Glide add SupportRequestManagerFragment purpose is to monitor fragments or the Activity of the life cycle, when the interface is visible to perform/restore image loading request, interface invisible stop the request of the loading images, interface destroy the execution resources to release some of the operation.

This is Glide on picture loading one of the optimization measures to reduce resource waste

4. Case 3: PermissionX Library application Practice

This library is to implement permission application, and permission application must be inseparable from Activity. In order not to invade the logic of the business layer as much as possible, here cleverly uses the method of adding Fragment to implement permission application and callback processing:

class InvisibleFragment : Fragment() {
    private val requestWriteSettingsLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
    // Permission request callback processing
        onRequestWriteSettingsPermissionResult()
    }
    // Initiate permission request
    fun requestWriteSettingsPermissionNow(permissionBuilder: PermissionBuilder, chainTask: ChainTask) {
        requestWriteSettingsLauncher.launch(intent)
    }
}
Copy the code

The above permission application is written using Activity ResultAPI. For specific usage, you can see Guo Shen’s article.

Add:

private val invisibleFragment: InvisibleFragment
    get() {
        val existedFragment = fragmentManager.findFragmentByTag(FRAGMENT_TAG)
        return if(existedFragment ! =null) {
            existedFragment as InvisibleFragment
        } else {
            val invisibleFragment = InvisibleFragment()
            fragmentManager.beginTransaction()
                .add(invisibleFragment, FRAGMENT_TAG)
                .commitNowAllowingStateLoss()
            invisibleFragment
        }
    }
Copy the code

Source code is very simple, the principle and the beginning of the same, we can see.