Observer mode of Android design mode

Introduction to Observer Pattern

Observer mode is a mode with a very high usage rate. It is most commonly used in GUI systems and subscription-publishing systems. Because an important function of this mode is decoupling, decoupling the observer and the observed, making them less dependent, or even independent.

Definition of observer mode: Define a one-to-many dependency relationship between objects, so that whenever an object changes state, all objects that depend on it will be notified and automatically updated.

The UML class diagram of the observer mode, as shown in the figure

Character introduction:

(1) Subject (observed) The object to be observed. When the state that needs to be observed changes, all observer objects in the queue need to be notified. Subject needs to maintain (add, delete, notify) a queue list of observer objects. the
(2) ConcreteSubject The specific implementation of the observer. Contains some basic attribute states and other operations. the
(3) Observer (observer) interface or abstract class. When the state of the Subject changes, the Observer object will be notified through a callback function. the
(4) The specific implementation of the ConcreteObserver observer. After being notified, some specific business logic processing will be completed.

JDK provides support for the observer design pattern:

  • Play the role of Subject through the java.util.Observable class, and a class can play the role of ConcreteSubject only by inheriting the java.util.Observable class;
  • Through the java.util.Observer interface to play the role of Observer, a class can play the role of ConcreteObserver only by implementing the java.util.Observer interface.
  • The implementation class of java.util.Observable can simply notify the Observer by calling the setChanged() method and the notifyObservers(Object) method.

A simple implementation of the observer pattern

Those who play LOL games know that Tencent servers will regularly update the game version, such as adding new heroes. will notify all Player s who have installed the LOL client, the code implementation is as follows:

First write a player Player class as an observer:

import java.util.Observable;
import java.util.Observer;

public class Player implements Observer{//Inherit the Observer interface

    public String name;//Name
    public Player(String aName){
        name=aName;
    }
    //Override the update() method of the parent class
    @Override
    public void update(Observable o, Object arg) {
        // TODO Auto-generated method stub
        System.out.println("Hello,"+name+",LOL Updated, content:"+arg);
    }

    @Override
    public String toString() {
        return "player:"+name;
    }
}

Then the LOLServer class, as the observer:

import java.util.Observable;

public class LOLServer extends Observable{
    public void postNewPublication(String content){
        //Flag content or state changes
        setChanged();
        //notify all observers
        notifyObservers(content);
    }
}

The specific observer publishes the updated content to each observer Test class:

public class Test {
    public static void main(String[] args) {
        //1 Create the observed role
        LOLServer lolServer=new LOLServer();
        //2 Create observers
        Player player1=new Player("Robin Li");
        Player player2=new Player("Jack Ma");
        Player player3=new Player("Ma Huateng");
        //3 Register the observer to the observer list of the observable object
        lolServer.addObserver(player1);
        lolServer.addObserver(player2);
        lolServer.addObserver(player3);
        //4 Post a message
        lolServer.postNewPublication("Death is like the wind, always with me!");
    }
}

The printed results are as follows:

Hello,Ma Huateng,LOL Updated, content: Death is like the wind, always with me!
Hello,Jack Ma,LOL Updated, content: Death is like the wind, always with me!
Hello,Robin Li,LOL Updated, content: Death is like the wind, always with me!

Observer pattern in Android source code

ListView is one of the most important controls in Android, and one of the most important functions of ListView is Adapter. Usually, after we add data to the ListView, the notifyDataSetChanged of the Adapter will be called. This method is defined in the BaseAdapter. The specific code is as follows:

public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
    private final DataSetObservable mDataSetObservable = new DataSetObservable();
    public void registerDataSetObserver(DataSetObserver observer) {
        mDataSetObservable.registerObserver(observer);
    }
    public void unregisterDataSetObserver(DataSetObserver observer) 
    {
        mDataSetObservable.unregisterObserver(observer);
    }
    //Notify all observers when the dataset changes
    public void notifyDataSetChanged() {
        mDataSetObservable.notifyChanged();
    }
}

Here BaseAdapter is an observer pattern, so how does BaseAdapter work? Who is the observer? Who is the observed? How does the observed person publish new content? First, let's take a look at the mDataSetObservable.notifyChanged() function:

//Dataset Observer
public class DataSetObservable extends Observable<DataSetObserver> {
    /**
     * Invokes {@link DataSetObserver#onChanged} on each observer.
     * Called when the contents of the data set have changed.  The recipient
     * will obtain the new contents the next time it queries the data set.
     */
    public void notifyChanged() {
        synchronized(mObservers) {
        //Call the onChaged function of all observers to notify them that the observed has changed
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onChanged();
            }
        }
    }

This code is very simple. It traverses all observers in a for loop and calls their onChanged method to notify the observer that a change has occurred.

So where do these watchers come from? In fact, these observers are generated by ListView setting the Adapter through the setAdapter method. The relevant code is as follows:

    @Override
    public void setAdapter(ListAdapter adapter) {
    //If there is already an Adapter, first log out of the observer corresponding to the adapter
        if (mAdapter != null && mDataSetObserver != null) {
            mAdapter.unregisterDataSetObserver(mDataSetObserver);
        }
       //Code omitted
        super.setAdapter(adapter);

        if (mAdapter != null) {
            mOldItemCount = mItemCount;
            mItemCount = mAdapter.getCount();//Get the total number of data
            mDataChanged = true;
            checkFocus();
          //Create a dataset observer
            mDataSetObserver = new AdapterDataSetObserver();
           mAdapter.registerDataSetObserver(mDataSetObserver);//Registering this observer to the Adapter is actually registered to the DataSetObservable
            //Code omitted
            requestLayout();
    }

In the code, we can see that when setting the adapter, an AdapterDataSetObserver will be built, which is the observer mentioned above, and finally the observer of AdapterDataSetObserver will be registered in the Adapter, so that our observer and the observed person already have So, what is AdapterDataSetObserver actually? How does it work?

Let's take a look at AdapterDataSetObserver, which is defined in the parent class AbsListView of ListView. The specific code is as follows:

 class AdapterDataSetObserver extends AdapterView<ListAdapter>.AdapterDataSetObserver {
        @Override
        public void onChanged() {
            super.onChanged();
            if (mFastScroller != null) {
                mFastScroller.onSectionsChanged();
            }
        }

        @Override
        public void onInvalidated() {
            super.onInvalidated();
            if (mFastScroller != null) {
                mFastScroller.onSectionsChanged();
            }
        }
    }

It inherits from the AdapterDataSetObserver of AdapterView, the parent class of AbsListView. The specific code is as follows:

 class AdapterDataSetObserver extends DataSetObserver {

        private Parcelable mInstanceState = null;
//As mentioned above, when the notifyDataSetChanged of the adapter is called, the onChanged method of all observers will be called, and the core implementation is here
        @Override
        public void onChanged() {
            mDataChanged = true;
            mOldItemCount = mItemCount;
            mItemCount = getAdapter().getCount();//Get the total amount of data in the adapter
            if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null
                    && mOldItemCount == 0 && mItemCount > 0) {      AdapterView.this.onRestoreInstanceState(mInstanceState);
                mInstanceState = null;
            } else {
                rememberSyncState();
            }
            checkFocus();
            //Re-layout AdapterView components such as Listview and GridView
            requestLayout();
        }
        public void clearSavedState() {
            mInstanceState = null;
        }
    }

So far we know that when the data of the ListView changes, the notifyDataSetChanged function of the Adapter is called, which in turn calls the notifyChanged function of the DataSetObservable, which in turn calls the onChanged method of all observers (AdapterDataSetObserver), in the onChanged function It will call the requestLayout function of ListView to re-layout to make ListView re-refresh the interface. This is an observer mode.

Summarize:  
The main function of the observer mode is to decouple objects, completely isolate the observer from the observed, and only rely on the abstraction of Observer and Observable.


Reprinted from: http://blog.csdn.net/happy_horse/article/details/51541125

Tags: Android

Posted by fr8 on Mon, 28 Nov 2022 03:41:15 +1030