Analysis of Glide binding life cycle and callback monitoring principle

 

Glide.with(this).load(url).into(imageview)

The life cycle of Glide binding fragment and Activity is executed in the with method. With can call the corresponding get method directly for fragment, Activity, FragmentActivity, Context and View. If it is Context or View, judge the type of the Context. If it is fragment, create another default fragment and return requ Estmanager, otherwise the default fragment will not be created, and it will return to RequestManager directly. Let's take a look at how to create an empty fragment to bind the lifecycle.

I. creation of RequestManagerFragment

For example, get method of Fragment:

  public RequestManager get(@NonNull Fragment fragment) {
    if (Util.isOnBackgroundThread()) {
      return get(fragment.getContext().getApplicationContext());
    } else {
      //Get fm according to activity.getChildFragmentManager()
      FragmentManager fm = fragment.getChildFragmentManager();
      return supportFragmentGet(fragment.getContext(), fm, fragment, fragment.isVisible());
    }
  }
  •    Activity -> activity.getFragmentManager() —> FragmentManager
  •    Fragment -> activity.getChildFragmentManager() —> FragmentManager
  •    FragmentActivity -> activity.getSupportFragmentManager() —> FragmentManager

Whether Activity, Fragment or FragmentActivity will create FragmentManager, and then call the fragmentGet/supportFragmentGet method, this is the key to generating the management lifecycle. When adding, it should be noted that fm.beginTransaction().add method is used to add to the current fragment or activity, and then it is sent to the main thread in commitAllowingStateLoss.

  @NonNull
  private RequestManager supportFragmentGet(
	  @NonNull Context context,
	  @NonNull FragmentManager fm,
	  @Nullable Fragment parentHint,
	  boolean isParentVisible) {
	//Generate SupportRequestManagerFragment
	SupportRequestManagerFragment current =getSupportRequestManagerFragment(fm, parentHint, isParentVisible);
	//Get request management class
	RequestManager requestManager = current.getRequestManager();
	if (requestManager == null) {
	  //If the request management class is empty, the object is generated
	  Glide glide = Glide.get(context);
	  requestManager =factory.build(glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
	  current.setRequestManager(requestManager);
	}
	return requestManager;
  }

  //Generate SupportRequestManagerFragment
  private SupportRequestManagerFragment getSupportRequestManagerFragment(
	  @NonNull final FragmentManager fm, @Nullable Fragment parentHint, boolean isParentVisible) {
	//Find current according to TAG. The TAG here is a fixed value, that is, there is only one fragment
	SupportRequestManagerFragment current =(SupportRequestManagerFragment) fm.findFragmentByTag(FRAGMENT_TAG);
	if (current == null) {
	  //If it is empty
	  current = pendingSupportRequestManagerFragments.get(fm);
	  if (current == null) {
		//If you don't come in for the first time, you will create
		current = new SupportRequestManagerFragment();
		current.setParentFragmentHint(parentHint);
		if (isParentVisible) {
		  current.getGlideLifecycle().onStart();
		}
		//Put it in the HashMap so that you can get it next time
		pendingSupportRequestManagerFragments.put(fm, current);
		//Note that the add method here adds an empty fragment with no id and only one TAG to the host fragment
		fm.beginTransaction().add(current, FRAGMENT_TAG).commitAllowingStateLoss();
		//Send to main thread
		handler.obtainMessage(ID_REMOVE_SUPPORT_FRAGMENT_MANAGER, fm).sendToTarget();
	  }
	}
	return current;
  }

After the above steps, the empty SupportRequestManagerFragment is generated. See the notes for the detailed process.

2, Life cycle binding of RequestManagerFragment

RequestManagerFragment is an empty fragment. It has no layout or View operations and is only used to monitor the lifecycle.

    public RequestManagerFragment() {
        this(new ActivityFragmentLifecycle());
    }

    RequestManagerFragment(@NonNull ActivityFragmentLifecycle lifecycle) {
        this.lifecycle = lifecycle;
    }

1,ActivityFragmentLifecycle

An ActivityFragmentLifecycle object will be created in the parameterless construction method of RequestManagerFragment. It is a callback listener of the Lifecycle and implements the Lifecycle interface. Responsible for registering and removing the Lifecycle listener. In addition, there are three methods: onStart, onStop and onDestroy. In these three methods, you can traverse the Set to get the corresponding method of the LifecycleListener. The LifecycleListener here is actually the RequestManager, that is, the three methods of calling RequestManager.

    class ActivityFragmentLifecycle implements Lifecycle {

      private final Set<LifecycleListener> lifecycleListeners =
          Collections.newSetFromMap(new WeakHashMap<LifecycleListener, Boolean>());
      private boolean isStarted;
      private boolean isDestroyed;

      //Registered monitoring
      @Override
      public void addListener(@NonNull LifecycleListener listener) {
        lifecycleListeners.add(listener);

        if (isDestroyed) {
          listener.onDestroy();
        } else if (isStarted) {
          listener.onStart();
        } else {
          listener.onStop();
        }
      }

     //Remove listening
      @Override
      public void removeListener(@NonNull LifecycleListener listener) {
        lifecycleListeners.remove(listener);
      }

      void onStart() {
        isStarted = true;
        for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
          lifecycleListener.onStart();
        }
      }

      void onStop() {
        isStarted = false;
        for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
          lifecycleListener.onStop();
        }
      }

      void onDestroy() {
        isDestroyed = true;
        for (LifecycleListener lifecycleListener : Util.getSnapshot(lifecycleListeners)) {
          lifecycleListener.onDestroy();
        }
      }
    }

2. RequestManagerFragment lifecycle delivery

After creating the RequestManagerFragment, when the current page is loaded, the life cycle is passed to the RequestManagerFragment, and the method of the object's life cycle is executed. When the onStart is executed, the onStart of the activityfragment life cycle is called. When the onStop is executed, the onStop of the activityfragment life cycle is called In this way, ActivityFragmentLifecycle will call methods such as lifecycleListener.onStart(), and give the callback to ActivityFragmentLifecycle.

3. Request management in the life cycle of RequestManager

After the RequestManagerFragment is created by the with method, it will return fragmentGet()/supportFragmentGet(). This method directly returns a RequestManager. Take a look at the supportFragmentGet code in the first part:

   private RequestManager supportFragmentGet(
        ..................................................................
        //Get request management class
        RequestManager requestManager = current.getRequestManager();
        if (requestManager == null) {
          //If the request management class is empty, the object is generated
          Glide glide = Glide.get(context);
          requestManager =factory.build(glide, current.getGlideLifecycle(), current.getRequestManagerTreeNode(), context);
          current.setRequestManager(requestManager);
        }
        return requestManager;
   }

RequestManager implements the LifecycleListener interface, passing the current.getGlideLifecycle() parameter in the construction method, which is the ActivityFragmentLifecycle, and then immediately calls the addListener method of ActivityFragmentLifecycle to register, so that when the ActivityFragmentLifecycle management class executes the corresponding lifecycle, it will call RequestManager The corresponding method of. The corresponding onStart will start the network request, and set the onStart method of ImageView listening to ImageView, and the onStart method will listen to it.

    public class RequestManager implements LifecycleListener, ......{

      @Override
      public synchronized void onStart() {
        //Initiate request
        resumeRequests();
        //View's Target callback
        targetTracker.onStart();
      }

      @Override
      public synchronized void onStop() {
        //Pause request
        pauseRequests();
         //View's Target callback
        targetTracker.onStop();
      }

      @Override
      public synchronized void onDestroy() {
        ////Destruction request
        targetTracker.onDestroy();
        //View's Target callback
        for (Target<?> target : targetTracker.getAll()) {
          clear(target);
        }
        //Clear callback information
        targetTracker.clear();
        requestTracker.clearRequests();
        lifecycle.removeListener(this);
        lifecycle.removeListener(connectivityMonitor);
        mainHandler.removeCallbacks(addSelfToLifecycle);
        glide.unregisterRequestManager(this);
      }
    }

In this way, instead of manual callback of onStart, onStop and onDestroy, the RequestManagerFragment callback is used to manage a series of actions such as request initiation and destruction skillfully, which saves more memory and avoids memory leakage.

Three, summary

  1. Create an empty fragment from the context object to synchronize the lifecycle.
  2. Create the life cycle management class ActivityFragmentLifecycle in the fragment construction method, initialize the RequestManager, and register with the LifecycleListener.
  3. Call back the life cycle method corresponding to the ActivityFragmentLifecycle when the fragment is executed.
  4. When the ActivityFragmentLifecycle method is executed, the RequestManager is called to initiate the request and cancel the request. At the same time, call back to the Target of the current View to monitor the client.
     

The flow chart is as follows:

 

 

108 original articles published, 24 praised, 160000 visitors+
Private letter follow

Tags: Fragment network Spring

Posted on Sun, 12 Jan 2020 03:38:50 -0500 by dc2000