MVC架构的优点就不介绍了不过说实话,在小项目里用MVC,相对而言,确实复杂了。状态模式是指让一个对象在其内部状态改变的时候,其行为也随之改变。状态模式需要对每一个系统可能取得的状态创立一个状态类的子类。当系统的状态变化时,系统便改变所选的子类。下面的一个例子是模拟下载文件,不同的状态,点击按钮有不同的动作,使用Handler在Controller和Activity之间传递消息,以执行不同的操作,改变UI。范例独立出了Controller,并没有把Activity当Controller。 先看图: 就是点击Download按钮,改变进度条。 先写Model.java:
package models;
import java.util.ArrayList;
import java.util.List;
import android.os.SystemClock;
public class Model {
private String url;
private long totalSize, downloadedSize;
//监听器,可以添加多个
private final List listeners = new ArrayList();
//标记是否被取消
private boolean cancelFlag = false;
public Model(String url) {
this.url = url;
}
public interface Listener {
void onProgressUpdated(Model model);
void onCompleted(Model model);
}
/**
* 下载,耗时操作
*/
public void download() {
cancelFlag = false;
totalSize = 100;
while (downloadedSize < 100 && !cancelFlag) {
SystemClock.sleep(1000);
downloadedSize++;
// 加上同步块,避免迭代时add或remove
synchronized (listeners) {
for (Listener listener : listeners) {
listener.onProgressUpdated(this);
}
if (downloadedSize == totalSize) {
for (Listener listener : listeners) {
listener.onCompleted(this);
}
}
}
}
// 取消后重置下载计数
if (cancelFlag) {
downloadedSize = 0;
}
}
/**
* 取消下载
*/
public void cancel() {
cancelFlag = true;
}
public void addListener(Listener listener) {
synchronized (listeners) {
listeners.add(listener);
}
}
public void removeListener(Listener listener) {
synchronized (listeners) {
listeners.remove(listener);
}
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public long getTotalSize() {
return totalSize;
}
public void setTotalSize(long totalSize) {
this.totalSize = totalSize;
}
public long getDownloadedSize() {
return downloadedSize;
}
public void setDownloadedSize(long downloadedSize) {
this.downloadedSize = downloadedSize;
}
}
接口ControllerProtocol,用于保存常量,这样,只要实现了该接口的类都会有相同的常量,这里主要是保存Message的what值。
package controllers;
/**
* 用于共享常量,所有实现该接口的类都可以使用这些常量
* @author fhp
*
*/
public interface ControllerProtocol {
/**Message的what值**/
public final int W_REQUEST_DOWNLOAD=1,W_REQUEST_CANCEL=2, W_TOAST=3,W_UPDATE=4,W_COMPLETE=5;
}
ControllerState.java,三种不同状态:未下载,正在下载,下载完成
package controllers;
import android.os.Message;
/**
* 不同状态
* @author fhp
*
*/
public abstract class ControllerState {
protected Controller controller;
public ControllerState(Controller controller)
{
this.controller=controller;
}
public abstract boolean handleMessage(Message msg);
}
/**
* 未开始下载状态,默认值
* @author fhp
*
*/
final class NotStartState extends ControllerState implements ControllerProtocol{
public NotStartState(Controller controller) {
super(controller);
// TODO 自动生成的构造函数存根
}
@Override
public boolean handleMessage(Message msg) {
// TODO 自动生成的方法存根
switch(msg.what)
{
case W_REQUEST_DOWNLOAD:
controller.notifyOutboxHandlers(W_TOAST, 0, 0, "开始下载!");
controller.changeState(new DownloadingState(controller));
break;
case W_REQUEST_CANCEL:
controller.notifyOutboxHandlers(W_TOAST, 0, 0, "下载未开始,不用取消!");
break;
}
return false;
}
}
/**
* 正在下载的状态
* @author fhp
*
*/
final class DownloadingState extends ControllerState implements ControllerProtocol{
public DownloadingState(final Controller controller) {
super(controller);
// 切换到下载状态时,开始下载。不能用Controller里的HandlerThread下载,虽然不会阻塞UI,但会阻塞消息传递
new Thread(){
public void run()
{
controller.getModel().download();
}
}.start();
}
@Override
public boolean handleMessage(Message msg) {
// TODO 自动生成的方法存根
switch(msg.what)
{
case W_REQUEST_DOWNLOAD:
controller.notifyOutboxHandlers(W_TOAST, 0, 0, "下载已开始!");
break;
case W_REQUEST_CANCEL:
controller.getModel().cancel();
controller.changeState(new NotStartState(controller));
controller.notifyOutboxHandlers(W_TOAST, 0, 0, "下载取消!");
break;
}
return false;
}
}
/**
* 下载完成状态
* @author fhp
*
*/
final class CompletedState extends ControllerState implements ControllerProtocol{
public CompletedState(Controller controller) {
super(controller);
}
@Override
public boolean handleMessage(Message msg) {
switch(msg.what)
{
case W_REQUEST_DOWNLOAD:
controller.notifyOutboxHandlers(W_TOAST, 0, 0, "下载已完成!");
break;
case W_REQUEST_CANCEL:
controller.notifyOutboxHandlers(W_TOAST, 0, 0, "下载完成,不能取消!");
break;
}
return false;
}
}
Controller.java:
package controllers;
import java.util.ArrayList;
import java.util.List;
import models.Model;
import models.Model.Listener;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Message;
public class Controller implements Handler.Callback,ControllerProtocol {
//收信Handler
private Handler inBoxHandler;
//发信Handler
private List outBoxHandlers = new ArrayList();
private Model model;
//状态模式,状态改变,改变state
private ControllerState state;
public Controller(Model model) {
this.model = model;
// 默认没开始状态
this.state = new NotStartState(this);
inBoxHandler = new Handler(this);
//增加监听器
this.model.addListener(new Listener() {
@Override
public void onProgressUpdated(Model model) {
// TODO 自动生成的方法存根
notifyOutboxHandlers(W_UPDATE,0,0,model);
}
@Override
public void onCompleted(Model model) {
// TODO 自动生成的方法存根
notifyOutboxHandlers(W_COMPLETE,0,0,model);
changeState(new CompletedState(Controller.this));
}
});
}
/**
* 改变状态
*
* @param state
*/
public void changeState(ControllerState state) {
this.state = state;
}
public void addOutBoxHandler(Handler handler) {
outBoxHandlers.add(handler);
}
public Handler getInBoxHandler() {
return inBoxHandler;
}
public Model getModel() {
return model;
}
@Override
public boolean handleMessage(Message msg) {
// 收到消息后(这里就是点击事件),转发给ControllerState处理,不同的State处理方法不同
return state.handleMessage(msg);
}
/**
* 消息发给所有的Handler,例子里只有一个
* @param what
* @param arg1
* @param arg2
* @param obj
*/
public void notifyOutboxHandlers(int what, int arg1, int arg2, Object obj) {
for (Handler handler : outBoxHandlers) {
Message msg = Message.obtain(handler, what, arg1, arg2, obj);
msg.sendToTarget();
}
}
}
最后是activity:
package com.pocketdigi.mvcdemo;
import models.Model;
import controllers.Controller;
import controllers.ControllerProtocol;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity implements Handler.Callback,OnClickListener,ControllerProtocol{
private TextView tv_count;
private Button btn_down,btn_cancel;
private ProgressBar progressBar;
//独立的Controller
private Controller controller;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViews();
controller=new Controller(new Model("http://www.pocketdigi.com"));
controller.addOutBoxHandler(new Handler(this));
}
private void findViews()
{
tv_count=(TextView)findViewById(R.id.tv_count);
btn_down=(Button)findViewById(R.id.btn_down);
btn_cancel=(Button)findViewById(R.id.btn_cancel);
progressBar=(ProgressBar)findViewById(R.id.progressBar);
btn_down.setOnClickListener(this);
btn_cancel.setOnClickListener(this);
}
@Override
public boolean handleMessage(Message msg) {
// TODO 自动生成的方法存根
switch(msg.what)
{
case W_TOAST:
String string=(String)msg.obj;
showToast(string);
break;
case W_UPDATE:
Model model=(Model)msg.obj;
double percent=model.getDownloadedSize()/(double)model.getTotalSize()*100;
progressBar.setProgress((int)percent);
tv_count.setText(String.format("%1$.2f%%", percent));
break;
case W_COMPLETE:
showToast("下载完成");
break;
}
return false;
}
private void showToast(String string)
{
Toast.makeText(this, string, Toast.LENGTH_SHORT).show();
}
@Override
public void onClick(View v) {
switch(v.getId())
{
case R.id.btn_down:
controller.getInBoxHandler().sendEmptyMessage(W_REQUEST_DOWNLOAD);
break;
case R.id.btn_cancel:
controller.getInBoxHandler().sendEmptyMessage(W_REQUEST_CANCEL);
break;
}
}
}
源码下载链接: http://pan.baidu.com/s/1o6rv0BS