26设计模式之观察者模式


观察者模式是一种使用非常多,也非常有用的一种设计模式。该模式有2种对象,一种是被观察者,一种是观察者。被观察者是唯一的,观察者可以有多个,是一种一对多的关系。举个例子,好比我们去追一部正在更新的电视剧,这部电视剧就是我们被观察者而追电视剧的人就是观察者,如何在电视剧更新的时候追电视剧的人第一时间知道就是观察者模式需要解决的这类问题。在安卓中使用观察中是非常简单的,因为这两种对象Google已经帮我们分装好类了,我们只需要直接用就可以了,下面是分装好的两个类及常用的方法。

Observer(观察者),是一个接口类,只需要重写update方法就可以了,该方法在被观察者通知观察者数据改变时调用。

Observerable(被观察者),是一个类,常用的方法如下:

setChanged():数据改变时调用。

addObserver():添加观察者时调用。

下面我们就来使用者两个类演示一个示例,示例的效果是这样的,我们用观察者去观察一个图片下载的过程,如果图片下载完成就通知观察者去更新imageview上面的图片。

首先新建一个类继承Observerable类,里面代码如下:

public class MyObserverable extends Observable {
	// 数据改变时调用
	@Override
	protected void setChanged() {
		super.setChanged();
		Log.e("", "数据改变了!");
	}

	// 添加观察者时调用
	@Override
	public void addObserver(Observer observer) {
		super.addObserver(observer);
		Log.e("", "新增加了一个观察者!");
	}

	
}
MainActivity类实现Observer接口,重写update方法, update里的代码如下:

	@Override
	public void update(Observable observable, Object data) {
		// 将下载的图片显示到ImageView上面
		imgv.post(new Runnable() {
			@Override
			public void run() {
				imgv.setImageBitmap(bm);
			}
		});
	}

Activity布局文件如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <Button
        android:id="@+id/btn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="下载图片" />

    <ImageView
        android:id="@+id/imgv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/btn"
        android:scaleType="centerInside"
        android:src="@drawable/ic_launcher" />

</RelativeLayout>

给按钮添加一个监听事件代码如下:

	// 下载图片
		btn.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				new Thread(new Runnable() {
					@Override
					public void run() {
						try {
							HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
							conn.setReadTimeout(5 * 1000);
							conn.setConnectTimeout(5 * 1000);
							// 将输入流转换为图片
							bm = BitmapFactory.decodeStream(conn.getInputStream());

						} catch (MalformedURLException e) {
							e.printStackTrace();
						} catch (IOException e) {
							e.printStackTrace();
						}

						// 设置数据改变
						observerable.setChanged();
						// 通知观察者
						observerable.notifyObservers();
					}
				}).start();

			}
		});

点击按钮去下载一张图片,记得添加网络访问权限, 在oncreate方法里面我们做如下工作:

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		// 实例化observerable对象
		observerable = new MyObserverable();
		// 将自己添加到观察队列中
		observerable.addObserver(this);
		init();
	}
完整的MainActivity代码如下:

public class MainActivity extends Activity implements Observer {
	private ImageView imgv;
	private Button btn;
	private MyObserverable observerable;
	private Bitmap bm;
	private String url = "http://cdn.duitang.com/uploads/item/201409/05/20140905015324_zvwG2.png";

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		// 实例化observerable对象
		observerable = new MyObserverable();
		// 将自己添加到观察队列中
		observerable.addObserver(this);
		init();
	}

	private void init() {
		imgv = (ImageView) findViewById(R.id.imgv);
		btn = (Button) findViewById(R.id.btn);
		// 下载图片
		btn.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				new Thread(new Runnable() {
					@Override
					public void run() {
						try {
							HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
							conn.setReadTimeout(5 * 1000);
							conn.setConnectTimeout(5 * 1000);
							// 将输入流转换为图片
							bm = BitmapFactory.decodeStream(conn.getInputStream());

						} catch (MalformedURLException e) {
							e.printStackTrace();
						} catch (IOException e) {
							e.printStackTrace();
						}

						// 设置数据改变
						observerable.setChanged();
						// 通知观察者
						observerable.notifyObservers();
					}
				}).start();

			}
		});
	}

	@Override
	public void update(Observable observable, Object data) {
		// 将下载的图片显示到ImageView上面
		imgv.post(new Runnable() {
			@Override
			public void run() {
				imgv.setImageBitmap(bm);
			}
		});
	}

}

MainActivity类实现观察者接口,将自己添加到观察队列中,点击按钮下载图片,下载完成使用被观察者通知观察者更新UI, 下面来看运行效果:

输出的Log:


扫描关注我的微信公众号:



最后有一个注意的问题,update方法并不是运行在主线程中而是在notifyObservers调用的线程中运行。附上下载demo:demo


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值