代码中的设计模式----观察者模式(动态刷新ListView)

观察者模式,使用过RxJava的应该都体验过,这就是一个标准的观察者模式,通过监听数据的变化,来刷新界面,这也复合MVVM架构思想。

1 简单的观察者模式

观察者模式需要的对象:
1 抽象的观察者:提供更新方法,接收消息;
2 具体的观察者:接收消息的具体实现,做后续操作;
3 抽象的被观察者:接收订阅者,给订阅者发消息,移除订阅者;
4 具体的被观察者:具体实现。

还是拿微信公众号发消息来说,这可能是老生常谈了。

/**
 * 抽象观察者
 */
public interface IObserver {
    /**
     * 数据更新
     * @param message 接收到的数据
     */
    void update(String message);
}

/**
 * 具体的观察者
 */
public class XiaoMing implements IObserver{


    @Override
    public void update(String message) {

        System.out.println("XiaoMing接收到了:"+message);
    }
}
/**
 * 抽象的被观察者
 */
public interface IObservable {

    void subscribe(IObserver observer);
    void remove(IObserver observer);
    void push(String message);
}

/**
 * 具体的被观察者
 */
public class BasketballObservable implements IObservable{

    private List<IObserver> userList;

    public BasketballObservable(){

        userList = new ArrayList<>();
    }

    //订阅者
    @Override
    public void subscribe(IObserver observer) {

        if(!userList.contains(observer)){

            userList.add(observer);
        }
    }
    //移除订阅者
    @Override
    public void remove(IObserver observer) {

        if(userList.contains(observer)){

            userList.remove(observer);
        }
    }

    @Override
    public void push(String message) {

        for (IObserver observer :
                userList) {
            //给订阅者发消息
            observer.update(message);
        }
    }
}

小明订阅了篮球公众号,公众号给小明发消息。

//订阅者小明
IObserver observer = new XiaoMing();

BasketballObservable observable = new BasketballObservable();
//小明订阅了篮球公众号
observable.subscribe(observer);
//发布公众号消息
observable.push("阿尔德里奇重回篮网!!");

运行结果:
XiaoMing接收到了:阿尔德里奇重回篮网!!

2 Java中的观察者模式

Java的Observer

public interface Observer {
    /**
     * 接收数据
     *
     * @param   o     被观察者
     * @param   arg   接收的数据
     *                 method.
     */
    void update(Observable o, Object arg);
}

具体的观察者James,实现了Java中的IObserver接口

public class James implements Observer {

    @Override
    public void update(Observable o, Object arg) {

        System.out.println("James接收到了:"+arg.toString());
    }
}

Java的Observable

public class Observable {
    //默认是false
    private boolean changed = false;
    //装载观察者的集合
    private Vector<Observer> obs;

    /** Construct an Observable with zero Observers. */

    public Observable() {
        obs = new Vector<>();
    }
    //添加观察者到集合中
    public synchronized void addObserver(Observer o) {
        if (o == null)
            throw new NullPointerException();
        if (!obs.contains(o)) {
            obs.addElement(o);
        }
    }

    /**
     * 移除观察者
     */
    public synchronized void deleteObserver(Observer o) {
        obs.removeElement(o);
    }
    
    //通知所有的观察者
    public void notifyObservers() {
        notifyObservers(null);
    }

    public void notifyObservers(Object arg) {
        /*
         * a temporary array buffer, used as a snapshot of the state of
         * current Observers.
         */
        Object[] arrLocal;

        synchronized (this) {
        	//如果
            if (!hasChanged())
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }
        
        //调用Observer的update方法
        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    }

    //清除全部的订阅者
    public synchronized void deleteObservers() {
        obs.removeAllElements();
    }

    /**
     * 设置改变状态
     */
    protected synchronized void setChanged() {
        changed = true;
    }

    /**
     * 
     */
    protected synchronized void clearChanged() {
        changed = false;
    }

    /**
     * Tests if this object has changed.
     *
     * @return  <code>true</code> if and only if the <code>setChanged</code>
     *          method has been called more recently than the
     *          <code>clearChanged</code> method on this object;
     *          <code>false</code> otherwise.
     * @see     java.util.Observable#clearChanged()
     * @see     java.util.Observable#setChanged()
     */
    public synchronized boolean hasChanged() {
        return changed;
    }

    /**
     * Returns the number of observers of this <tt>Observable</tt> object.
     *
     * @return  the number of observers of this object.
     */
    public synchronized int countObservers() {
        return obs.size();
    }
}
James james = new James();
WeatherObservable observable = new WeatherObservable();
//订阅
observable.addObserver(james);
//通知
observable.notifyObservers("明天气温降至-20摄氏度");

运行结果:空

为什么观察者没有接收到消息,看下源码。

public void notifyObservers(Object arg) {
        /*
         * a temporary array buffer, used as a snapshot of the state of
         * current Observers.
         */
        Object[] arrLocal;

        synchronized (this) {
        	//如果changed状态为false,那么直接return
            if (!hasChanged())
                return;
            arrLocal = obs.toArray();
            clearChanged();
        }
        
        //调用Observer的update方法
        for (int i = arrLocal.length-1; i>=0; i--)
            ((Observer)arrLocal[i]).update(this, arg);
    }

这里需要将changed字段的值置为true,代表数据状态发生改变,才可以通知到观察者。

James james = new James();
WeatherObservable observable = new WeatherObservable();
//订阅
observable.addObserver(james);
//将changed设置为true
observable.setChanged();
//通知
observable.notifyObservers("明天气温降至-20摄氏度");

运行结果:
James接收到了:明天气温降至-20摄氏度

3 ListView中的观察者模式

场景:动态添加数据,刷新ListView列表

3.1 优化观察者模式

在简单的观察者模式中,数据更新使用的数据是String字符串,不具备扩展性,需要优化一下,使用泛型。

/**
 * 抽象的观察者
 * @param <T> 观察的数据类型
 */
public interface IObserver<T> {

    void update(T t);
}
/**
 * 具体的观察者
 */
public abstract class Observer implements IObserver<Data>{

    @Override
    public void update(Data data) {

    }
}
/**
 * 被观察者
 * @param <T> 观察数据泛型
 * @param <O> 观察者泛型
 */
public class Observable<T,O extends IObserver<T>> {

    private List<O> observers;

    public Observable(){

        observers = new ArrayList<>();
    }

    public void subscribe(O o){
        if(!observers.contains(o)){

            observers.add(o);
        }
    }

    public void unSubscribe(O o){

        if(observers.contains(o)){

            observers.remove(o);
        }
    }

    public void push(T t){

        for (O observer :
                observers) {

            observer.update(t);
        }
    }
}

通过改进的观察者模式,更具有灵活性,可选择不同的数据类型传递。

public class DataInsertManager {

    //被观察者
    Observable<Data,IObserver<Data>> observable;

    private DataInsertManager(){

        observable = new Observable<>();
    }

    private static DataInsertManager mInstance;

    public static DataInsertManager getInstance(){

        if(mInstance == null){
            synchronized (DataInsertManager.class){

                if(mInstance == null){

                    mInstance = new DataInsertManager();
                }
            }
        }
        return mInstance;
    }


    public void Insert(Data data){
		//插入数据后,通知观察者更新数据
        observable.push(data);
    }

    public void register(IObserver observer){
        observable.subscribe(observer);
    }

    public void unRegister(IObserver observer){

        observable.unSubscribe(observer);
    }
}

这里将Activity界面作为观察者,动态观察数据的变化,当数据变化时,动态刷新ListView

public class DataActivity extends AppCompatActivity implements IObserver<Data> {

    private ListView lv_data;

    private DataAdapter mAdapter;

    private List<Data> dataList;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_data);

        lv_data = findViewById(R.id.lv_data);

        dataList = new ArrayList<>();

        setAdapter(this);

        //注册
        DataInsertManager.getInstance().register(this);
    }

    private void setAdapter(Context context) {

        if(mAdapter == null){

            mAdapter = new DataAdapter(context,dataList);
            lv_data.setAdapter(mAdapter);
        }else {
            //数据更新
            mAdapter.notifyDataSetChanged();
        }
    }

    public void addData(View view){

        EditText et_name,et_age;

        View view1 = View.inflate(this, R.layout.layout_insert, null);

        et_name = view1.findViewById(R.id.et_name);
        et_age = view1.findViewById(R.id.et_age);

        //插入数据
        Dialog dialog = new AlertDialog.Builder(this)
                .setView(view1)
                .setNegativeButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {

                        //插入数据
                        DataInsertManager.getInstance().
                                Insert(new Data(et_name.getText().toString(),
                                        et_age.getText().toString()));
                    }
                })
                .setPositiveButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {

                    }
                })
                .create();
        dialog.show();


    }
	//订阅接收到消息
    @Override
    public void update(Data data) {

        //数据更新
        dataList.add(data);
        //适配器刷新
        mAdapter.notifyDataSetChanged();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Awesome_lay

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值