English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
This article describes an example of Android programming design pattern - Observer Pattern. Shared for everyone's reference, as follows:
One, Introduction
Observer pattern is a highly used pattern, the most common places are GUI systems, subscription-publisher systems. Because one of the important roles of this pattern is decoupling, decoupling the observed and the observer, making their dependencies smaller, even to the point of no dependency. Taking GUI systems as an example, the UI of the application is variable, especially in the early stage, with the change of business or product requirements, the application interface will also change frequently, but the business logic changes little, at this time, the GUI system needs a set of mechanisms to deal with this situation, so that the UI layer is decoupled from the specific business logic, and the observer pattern comes into play at this time.
Two, Definition
Define a one-to-many dependency relationship between objects, so that whenever an object changes its state, all objects that depend on it will be notified and automatically updated.
Three, Application Scenarios
Associated behavior scenarios, it should be noted that associated behavior is divisible, rather than a 'composition' relationship.
Event multi-level triggering scenarios.
Cross-system message exchange scenarios, such as the processing mechanism of message queues and event buses.
Four, UML Class Diagram of Observer Pattern
UML Class Diagram:
Role Introduction:
Subject: Abstract theme, which is the role of the observer (Observable). The abstract theme role saves references to all observer objects in a collection, and each theme can have any number of observers. The abstract theme provides an interface to add and delete observer objects.
ConcreteSubject: The specific subject, which role stores relevant state in the specific observer object. When the internal state of the specific subject changes, it notifies all registered observers. The specific subject role is also called the specific observable (ConcreteObservable) role.
Observer: Abstract observer, which role is the abstract class of the observer, defining an update interface that allows the observer to update itself when receiving a change notification from the subject.
ConcreteObserver: The specific observer, which role implements the update interface defined by the abstract observer role, so that the state of the subject can be updated when the state changes.
5. Simple Implementation
Here is an example of following a TV series. Normally, to not miss the latest TV series, we would subscribe or follow this TV series. When the TV series is updated, it will be pushed to us first. Now let's simply implement it.
Abstract observer class:
/** * Abstract observer class, defines an interface for all concrete observers to update themselves when notified */ public interface Observer { /** * There is an update * * @param message Message */ public void update(String message); }
Abstract observable class:
/** * Abstract observable class */ public interface Observable { /** * Push message * * @param message Content */ void push(String message); /** * Subscription * * @param observer The subscriber */ void register(Observer observer); }
The specific observer class:
/** * The specific observer class, that is, the subscriber */ public class User implements Observer { @Override public void update(String message) { System.out.println(name + "," + message + "Updated!"); } // The name of the subscriber private String name; public User(String name) { this.name = name; } }
The specific observable class:
/** * The specific observable class, that is, the subscribed program */ public class Teleplay implements Observable{ private List<Observer> list = new ArrayList<Observer>();//Store subscribers @Override public void push(String message) { for(Observer observer:list){ observer.update(message); } } @Override public void register(Observer observer) { list.add(observer); } }
Implementation:
public class Client { public static void main(String[] args) { //The observed, here is the TV series subscribed by the user Teleplay teleplay = new Teleplay(); //Observer, here is the subscribed user User user1 = new User("Xiao Ming"); User user2 = new User("Xiao Guang"); User user3 = new User("Xiao Lan"); //Subscription teleplay.register(user1); teleplay.register(user2); teleplay.register(user3); //Push new message teleplay.push("xxx TV series"); } }
Result:
Xiao Ming, the xxx TV series has been updated! Xiao Guang, the xxx TV series has been updated! Xiao Lan, the xxx TV series has been updated!
From the above code, it can be seen that a one-to-many message push is implemented, and the push messages all depend on Observer and Observable these abstract classes, while User and Teleplay have no coupling, ensuring the flexibility and scalability of the subscription system.
Chapter 6: Observer Pattern in Android Source Code
1、BaseAdapter
BaseAdapter, I believe everyone is not unfamiliar, in the ListView adapter we all inherit it. Let's analyze it simply.
BaseAdapter part of the code:
public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter { //Data set observer private final DataSetObservable mDataSetObservable = new DataSetObservable(); public boolean hasStableIds() { return false; } public void registerDataSetObserver(DataSetObserver observer) { mDataSetObservable.registerObserver(observer); } public void unregisterDataSetObserver(DataSetObserver observer) { mDataSetObservable.unregisterObserver(observer); } /** * Notify all observers when the data set changes */ public void notifyDataSetChanged() { mDataSetObservable.notifyChanged(); } }
Let's look at the mDataSetObservable.notifyChanged() method:
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) { // since onChanged() is implemented by the app, it could do anything, including // removing itself from <@link mObservers> - and that could cause problems if // an iterator is used on the ArrayList <@link mObservers>. // to avoid such problems, just march through the list in reverse order. for (int i = mObservers.size() - 1; i >= 0; i--) { mObservers.get(i).onChanged(); } } } }
It can be seen that in mDataSetObservable.notifyChanged(), all observers are traversed, and their onChanged() is called to inform the observer of what has happened.
Then how does the observer come from, that is the setAdapter method, the code is as follows:
@Override public void setAdapter(ListAdapter adapter) { if (mAdapter != null && mDataSetObserver != null) { mAdapter.unregisterDataSetObserver(mDataSetObserver); } resetList(); mRecycler.clear(); if (mHeaderViewInfos.size() > 0 || mFooterViewInfos.size() > 0) { mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter); } mAdapter = adapter; } mOldSelectedPosition = INVALID_POSITION; mOldSelectedRowId = INVALID_ROW_ID; // AbsListView#setAdapter will update choice mode states. super.setAdapter(adapter); if (mAdapter != null) { mAreAllItemsSelectable = mAdapter.areAllItemsEnabled(); mOldItemCount = mItemCount; mItemCount = mAdapter.getCount(); checkFocus(); mDataSetObserver = new AdapterDataSetObserver(); mAdapter.registerDataSetObserver(mDataSetObserver);//Register observer ......Omitted } }
AdapterDataSetObserver is defined in the parent class AbsListView of ListView, which is a dataset observer, code:
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 is the AdapterDataSetObserver inherited from the parent class AdapterView of AbsListView, as follows:
class AdapterDataSetObserver extends DataSetObserver { private Parcelable mInstanceState = null; // As mentioned above, when calling notifyDataSetChanged of the Adapter, it will call the onChanged method of all observers, and the core implementation is right here @Override public void onChanged() { mDataChanged = true; mOldItemCount = mItemCount; // Get the number of data in the Adapter mItemCount = getAdapter().getCount(); // Detect the case where a cursor that was previously invalidated has // been repopulated with new data. if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null && mOldItemCount == 0 && mItemCount > 0) { AdapterView.this.onRestoreInstanceState(mInstanceState); mInstanceState = null; } rememberSyncState(); } checkFocus(); // Reorganize the AdapterView components such as ListView, GridView, etc. requestLayout(); } // Code is omitted public void clearSavedState() { mInstanceState = null; } }
When the data of ListView changes, the notifyDataSetChanged function of the Adapter is called. This function will call the notifyChanged function of DataSetObservable, which will call the onChanged method of all observers (AdapterDataSetObserver). This is an observer pattern!
7. Summary
Advantages:
The observer and the observed are abstractly coupled, and should respond to business changes.
Enhance the flexibility and scalability of the system.
Disadvantages:
When using the observer pattern, it is necessary to consider issues such as development efficiency and runtime efficiency. The program includes an observable, multiple observers, and the development and debugging content will be more complex. Moreover, in Java, the notification of messages is generally executed in order. If an observer is stuck, it will affect the overall execution efficiency. In this case, asynchronous implementation is generally adopted.
Readers who are interested in more content related to Android can check the special topics on this site: 'Android Development Tutorial for Beginners and Advanced', 'Summary of Android Debugging Skills and Common Problem Solutions', 'Summary of Usage of Android Basic Components', 'Summary of Techniques of Android View View', 'Summary of Techniques of Android Layout Layout', and 'Summary of Usage of Android Controls'.
I hope the content described in this article will be helpful to everyone in Android program design.
Declaration: The content of this article is from the Internet, and the copyright belongs to the original author. The content is contributed and uploaded by Internet users spontaneously. This website does not own the copyright, has not been manually edited, and does not assume any relevant legal liability. If you find any content suspected of copyright infringement, please send an email to: notice#w3Please replace # with @ when sending an email for reporting violations, and provide relevant evidence. Once verified, this site will immediately delete the content suspected of infringement.