When the observer mode and callback mechanism meet the Android source code

Source: Internet
Author: User

On a blog with you to share the Android source of the decorator mode, a little meaning, today with you to share the viewer mode in Android, by the way, the observer mode and the relationship between the callback mechanism, welcome everyone to shoot bricks.

Observer Pattern Definition

The Observer pattern defines a one-to-many dependency that allows multiple observer objects to listen to a Subject object at the same time. When the subject object changes in state, all observer objects are notified so that they can automatically update themselves.

Structure of the Observer pattern

The actors involved in the Observer pattern are:

    • Abstract theme (Subject) role: Abstract theme The role holds all references to observer objects in a single aggregation (such as a ArrayList object), each subject can have any number of observers. Abstract topics provide an interface that can add and remove observer objects, and abstract subject roles are also known as abstract Observer (Observable) roles.

    • Specific subject (ConcreteSubject) role: The status of the State is deposited into the specific observer object, and all registered observers are notified when the internal state of the specific subject changes. The specific subject role is also called the specific Observer (concrete Observable) role.

    • Abstract observer (OBSERVER) role: Defines an interface for all specific observers, updating themselves when the topic is notified, an interface called the update interface.
        

    • Specific observer (Concreteobserver) Role: Stores the state of the subject with the status itself. The specific observer role implements the update interface required by the abstract observer role in order to reconcile the state of itself with the state of the subject. If desired, the specific observer role can maintain a reference to a specific subject object.
Realize

Abstract Theme Role Classes

public abstract class Subject {    /**     * 用来保存注册的观察者对象     */    private    List<Observer> list = new ArrayList<Observer>();    /**     * 注册观察者对象     * @param observer    观察者对象     */    public void attach(Observer observer){        list.add(observer);        System.out.println("Attached an observer");    }    /**     * 删除观察者对象     * @param observer    观察者对象     */    public void detach(Observer observer){        list.remove(observer);    }    /**     * 通知所有注册的观察者对象     */    public void nodifyObservers(String newState){        for(Observer observer : list){            observer.update(newState);        }    }}

Specific Theme Role Classes

public class ConcreteSubject extends Subject{    private String state;    public String getState() {        return state;    }    public void change(String newState){        state = newState;        System.out.println("主题状态为:" + state);        //状态发生改变,通知各个观察者        this.nodifyObservers(state);    }}

Abstract Observer Role Class

public interface Observer {    /**     * 更新接口     * @param state    更新的状态     */    public void update(String state);}

Specific Observer Role classes

public class ConcreteObserver implements Observer {    //观察者的状态    private String observerState;    @Override    public void update(String state) {        /**         * 更新观察者的状态,使其与目标的状态保持一致         */        observerState = state;        System.out.println("状态为:"+observerState);    }}

Test class

public class Test {    public static void main(String[] args) {        //创建主题对象        ConcreteSubject subject = new ConcreteSubject();        //创建观察者对象        Observer observer = new ConcreteObserver();        //将观察者对象登记到主题对象上        subject.attach(observer);        //改变主题对象的状态        subject.change("new state");    }}
Two ways of realizing the viewer
    • Push

      The subject object pushes the details of the topic to the observer, and the information that is pushed is usually all or part of the data of the subject object, regardless of whether or not the observer needs them.

    • Pull

      The Subject object transmits only a small amount of information when it notifies the observer. If the observer needs more specific information, the Observer takes the initiative to get to the subject object, which is equivalent to the observer pulling data from the subject object. In the general implementation of this model, the subject object itself is passed to the observer through the update () method, which can be obtained by this reference when the observer needs to obtain the data.

Comparison of the two methods
    • The push model assumes that the subject object knows the data that the observer needs, whereas the pull model is a subject object that does not know what data the observer specifically needs, and simply passes itself to the observer, allowing the observer to take the value on its own.

    • The push model may make it difficult to reuse the observer object because the Observer's update () method is a parameter that is defined as needed, and may not be able to take into account the unused usage. This means that a new update () method may be available when a new situation arises, or simply a re-implementation of the observer, whereas the pull model does not cause this situation, because the parameters of the update () method are the subject object itself, This is basically the largest collection of data that a Subject object can deliver, and can be adapted to a variety of situations.

Callback mechanism and Observer pattern

There are many places in Android where callback mechanisms are used, such as the activity's life cycle, button click events, the thread's Run () method, and so on.

Here is the basic model of the callback:

public interface CallBack {      public void oncall();  }  public class A {      private CallBack callback;      //注册一个事件      public void register(CallBack callback){          this.callback = callback;      }      // 需要调用的时候回调      public void call(){          callback.oncall();      }  }  public static void main(String[] args) {      A a = new A();      a.register(new CallBack() {          @Override          public void oncall() {              System.out.println("回调函数被调用");          }      });      a.call();  

}

In this way, the callback mechanism is consistent with the observer pattern, except that the target class in the Observer pattern maintains a reference to all observers, and the callback only maintains a reference.

Viewer Mode in Android

The observer pattern is used extensively in Android, and event drivers are implemented in the framework layer based on the observer pattern. In addition, in the framework layer of the various services in the data changes, but also through the observer pattern to achieve upper-level data updates. Listener monitoring, GPS location information monitoring, and Broadcastreceiver are all based on the observer pattern. Let's talk about how the observer pattern in the ListView is implemented, and the Recyclerview is much the same, and the interest can be studied on its own.

Notifydatasetchanged of the ListView ()

Let's take a look at the structure of some observer patterns in the ListView

In order to facilitate the study of the relationship, we omitted some of the adapter part of the class relationship. Next we look at the specific invocation relationship.

First, we call adapter's notifydatasetchanged () method when we change the data.

/** * Common base class of Common implementation for a {@link Adapter} that can is * used in both {@link ListView} (by IM Plementing the Specialized * {@link ListAdapter} interface) and {@link Spinner} (by implementing the * Specialized {@link Spinneradapter} interface). */public Abstract class Baseadapter implements ListAdapter, Spinneradapter {private final datasetobservable Mdatasetob    servable = new Datasetobservable ();    public Boolean hasstableids () {return false;     } public void Registerdatasetobserver (Datasetobserver observer) {MDATASETOBSERVABLE.REGISTEROBSERVER (Observer); } public void Unregisterdatasetobserver (Datasetobserver observer) {Mdatasetobservable.unregisterobserver (ob    server);  }/** * Notifies the attached observers that the underlying data have been changed * and any View reflecting the     Data set should refresh itself.    */public void notifydatasetchanged () {mdatasetobservable.notifychanged (); }    /** * Notifies the attached observers, the underlying data is no longer valid * or available.     Once invoked this adapter are no longer valid and should * not report further data set changes.    */public void notifydatasetinvalidated () {mdatasetobservable.notifyinvalidated (); }}

Based on the above code we can navigate to the Mdatasetobservable.notifychanged () method.

/** * A Specialization of {@link Observable} for {@link Datasetobserver} * This provides methods for sending notifications To a list of * {@link Datasetobserver} objects. */public class Datasetobservable extends Observable<datasetobserver> {/** * invokes {@link Datasetobserver#o     NCHANGED} on each observer.  * Called when the contents of the data set has changed.     The recipient * would obtain the new contents the next time it queries the data set. */public void notifychanged () {synchronized (mobservers) {//since onChanged () are implemented by th E app, it could do anything, including//removing itself from {@link Mobservers}-and that could cause proble            Ms if//an iterator are used on the ArrayList {@link mobservers}.            To avoid such problems, just March thru the list in the reverse order.         for (int i = Mobservers.size ()-1; I >= 0; i--) {Mobservers.get (i). onChanged ();   }}}/** * invokes {@link datasetobserver#oninvalidated} on each observer. * Called when the data set is no longer valid and cannot being queried again, * such as when the data set has been closed     . */public void notifyinvalidated () {synchronized (mobservers) {for (int i = Mobservers.size ()-1; I >= 0;            i--) {mobservers.get (i). oninvalidated (); }        }    }}

We see that calling the Notifychanged () method will go through the mobservers and invoke the OnChange () method of all observers.

So the question is, when was the object of our observer added? Let's take a look at the place where the ListView was first associated with Baseadapter, the Setadapter (ListAdapter adapter) method.

@Overridepublic void setAdapter(ListAdapter adapter) {    //如果已经设置过了Adapter,那么取消注册对应的观察者。    if (mAdapter != null && mDataSetObserver != null) {        mAdapter.unregisterDataSetObserver(mDataSetObserver);    }    //省略部分代码    if (mAdapter != null) {        mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();        mOldItemCount = mItemCount;        mItemCount = mAdapter.getCount();        checkFocus();        //创建一个对应数据的观察者        mDataSetObserver = new AdapterDataSetObserver();        //间接调用DataSetObservable的注册方法        mAdapter.registerDataSetObserver(mDataSetObserver);        //省略部分代码    } else {        mAreAllItemsSelectable = true;        checkFocus();        // Nothing selected        checkSelectionChanged();    }    requestLayout();}

So our four characters are all,observable->subject;datasetobservable->concrete subject;datasetobserver->observer; Adapterdatasetobserver->concrete Observer. Then we found the place where we were registered.

Finally, the rest of our data is how to refresh the problem. Adapterdatasetobserver is defined in the parent class Abslistview of the ListView, and it inherits Adapterdatasetobserver from Abslistview's parent adapterview.

  class Adapterdatasetobserver extends Datasetobserver {private parcelable minstancestate = null; When we call adapter's Notifydatasetchanged the OnChanged method of all observers is called, and the core implementation is here @Override public void onChanged () {Mdata        Changed = true;        Molditemcount = Mitemcount;        Gets the number of data in the adapter Mitemcount = Getadapter (). GetCount ();        Detect the case where a cursor is previously invalidated have//been repopulated with new data.  if (AdapterView.this.getAdapter (). Hasstableids () && minstancestate! = null && molditemcount            = = 0 && mitemcount > 0) {AdapterView.this.onRestoreInstanceState (minstancestate);        Minstancestate = null;        } else {remembersyncstate ();        } checkfocus ();    Re-layout listview, GridView and other Adapterview Components Requestlayout ();    }//code omitted public void Clearsavedstate () {minstancestate = null; }} 

The Requestlayout () method is implemented in view and the sub-view is rewritten as required. Let's take a look at the notes.

/*call This when something have changed which have invalidated the layout of this view. This would schedule a layout pass of the view tree. /

Well, all of the call relationships here are basically clear. when the data of the ListView changes, call adapter's notifydatasetchanged function, which again calls the Datasetobservable notifychanged function, which invokes all observers ( Adapterdatasetobserver) method of onchanged. In the OnChanged function, you get a new number of datasets in adapter, and then call the ListView Requestlayout () method to re-layout and update the user interface.

Blind Summary

The ListView uses adapter and observer patterns to make scalability, flexibility, and low coupling, which I think is a good example of how design patterns are used in Android source code. So we're going to start thinking, do we have any more beautiful routines to implement the ListView component, and where can we apply this implementation idea?

Man is the reed that thinks, thinking about us becomes the great God in the eyes of others.

Reference Links:

Http://www.itdadao.com/articles/c15a265623p0.html

http://blog.csdn.net/bboyfeiyu/article/details/44040533

Http://www.cnblogs.com/mythou/p/3370340.html

When the observer mode and callback mechanism meet the Android source code

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.