Android MVC Part2 The Model

##MVC 基本概念 MVC 是一些设计模式组合在一起的框架模式。其中的模型(The Model)代表着程序的状态。要知道,对象(Object)由状态(属性)和行为(方法)组成。所以程序也要状态(The Model)。本质上, models 是一个键值对象,当里面的状态改变的时候发送事件。视图(The View)是用户看到并与之交互的对象。视图作为观察者绑定到模型中,当模型的状态改变,视图会得到通知并作出相应的更新。当用户与视图交互,视图会发送事件给控制器(The Controller)。控制器的作用就是处理输入逻辑,它解释用户的手势,更新模型,而且向视图反馈信息。下面是它们的关系图。 ##本项目的Model 在这个项目中,最主要的模型是 CounterVo 代码如下 :::java package com.lingavin.tapcounter.vos; public class CounterVo extends SimpleObservable<CounterVo>{ private int id =-1; public int getId(){ return id; } public void setId(int id){ this.id = id; notifyObservers(this); } private int count = 0; public int getCount(){ return count; } public void setCount(int count){ this.count = count; notifyObservers(this); } private String label=""; public String getLabel(){ return label; } public void setLabel(String label){ this.label = label; notifyObservers(this); } private boolean locked = false; public boolean isLocked(){ return locked; } public void setLocked(boolean locked){ this.locked = locked; notifyObservers(this); } @Override synchronized public CounterVo clone(){ CounterVo vo = new CounterVo(); vo.setId(id); vo.setLabel(label); vo.setCount(count); vo.setLocked(locked); return vo; } synchronized public void consume(CounterVo vo){ this.id = vo.getId(); this.label = vo.getLabel(); this.count = vo.getCount(); this.locked = vo.isLocked(); notifyObservers(this); } } SimpleObservable: ...

November 13, 2013

Android MVC Part3 The View

##什么是视图? 在 Android 中很多同学说 View 就是视图。但是 View 只有显示的能力,它不能处理响应和发送消息。先来看看视图的特点: 绑定模型 发送信息给控制器 处理控制器返回的信息 看来 activity 符合我们的要求,它可以绑定,可以处理信息,而且控制着 android 中所谓的 view 。但是 activity 又有一些其他的特性使它不像是 MVC 中的 V ,例如它管理着生命周期,而且它有一些像控制器的方法 boolean dispatchKeyEvent(KeyEvent event); boolean onOptionsItemSelected(MenuItem item); void onCreateContextMenu(….); so on…. 要知道 dispatchEvent 如果返回 true 表示这个 activity 会处理该事件。但是实际上,处理事件的逻辑应该交给控制器做的。 我们通过一些方法来避免上述的问题,使 activities 更像是一个视图。其灵感来源于这篇文章 为了把 activity 变成 view ,我们做了下面的操作。 ##1. 数据绑定 来看看 TapActivity 是如何绑定数据的 :::java package com.lingavin.tapcounter.activities; import com.lingavin.tapcounter.R; import com.lingavin.tapcounter.R.layout; import com.lingavin.tapcounter.vos.CounterVo; import com.lingavin.tapcounter.vos.OnChangeListener; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.widget.Button; import android.widget.CompoundButton; import android.widget.EditText; import android.widget.TextView; public class TapActivity extends Activity implements OnChangeListener { private static final String TAG = TapActivity.class.getSimpleName(); private CounterVo mCounterVo; private EditText label; private TextView count; private Button minusBtn; private Button plusBtn; private CompoundButton lockedBtn; private static final int UPDATE_VIEW = 0; private Handler mHandler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); int what = msg.what; switch(what){ case UPDATE_VIEW: updateView(); break; default: } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mCounterVo = new CounterVo(); mCounterVo.addListener(this); initViews(); } private void initViews() { lockedBtn = (CompoundButton) findViewById(R.id.lockBtn); ...... } @Override public void onChange(Object model) { mHandler.sendEmptyMessage(UPDATE_VIEW); } private void updateView(){ if(!label.getText().toString().equals(mCounterVo.getLabel())) label.setText(mCounterVo.getLabel()); label.setEnabled(!mCounterVo.isLocked()); count.setText(Integer.toString(mCounterVo.getCount())); lockedBtn.setChecked(mCounterVo.isLocked()); } } 在 onCreate 函数中我们实例化了 CounterVo 并把 TabActivity 作为观察者注册上 mCounterVo 。 ...

November 13, 2013

Android MVC Part1 Intro

##about 一直想寻找 android 关于基于 mvc 开发的教程, 但是国内的网站都讲得很空泛,最后在一个外国的 blog 里看到一系列的文章,介绍得很详细和具体,而且是基于项目的,所以转过来了。 这系列的文章不仅简述 MVC,还涉及到了状态模式的运用,如何用 Data Access Objects 来持久化数据,使用 web service 的命令来传递数据。这系列文章假设你已经了解用这些技术的好处,所以不会详细讲解为什么要这么用。 你可以通过点击这里查看原blog。 ##包管理 第一章先来建立工程并取好包名。好的包管理可以使明确你的类的大致作用,对编程有很大的帮助,试想下如果把所有 class 放到一个包中,当项目变大后,你想修改其中一个 class 将会是个噩梦。这里提供一个比较好的包的分类。 activities controllers daos lists models utils vos widgets 注意到所有的包名都是复数,因为里面不止一个 class 。上面的包名如果项目用不到可以删除。由包的名字我们就可以知道里面的类大致的功能,这就是好处。 activities – 很明显,这里会放入所有的 activity controllers – View 的大脑就放在这里面了 daos – 这里存放持久化逻辑 lists – 这里存放所有 list adapter models – 这里存放 View 绑定的 Model utils – 存放静态类和工具类 vos – 存放 Value Objects 也就是 POJOs 又或者 Data Transfer Objects widgets – 借鉴于android 存放定制化 widget part1 就到这里,源代码可以在这里下载 https://github.com/gavinlin/tapcounter ...

November 12, 2013

android中的强指针和弱指针

##Demo 从一个 demo 来感性认识一下 android 里面到处使用的 RefBase ,sp 和 wp 。 首先在 android 源码目录 external 中建立 weightpointer 目录。 在 weightpointer 目录建立 weightpointer.cpp :::cpp #include <stdio.h> #include <utils/RefBase.h> class WeightClass : public RefBase{ public: void printRefCount(){ int32_t strong = getStrongCount(); weakref_type *ref = getWeakRefs(); printf("*********************\n"); printf("Strong Ref Count: %d\n", (strong == INITAL_STRONG_VALUE? 0:strong)); printf("Weak Ref Count: %d\n", ref->getWeakCount()); printf("*********************\n"); } }; 编写 WeightClass 其继承了 RefBase 。实现了一个叫做printRefCount方法,作用就是通过调用 RefBase 相关接口,获得并打印生成对象的强引用和弱引用的信息。 ###StrongClass 接着实现一个叫做 StrongClass 的类。 ...

November 11, 2013

compile android4.4 on mavericks

最新的 android4.4 终于出来了。曾着新安装的 mavericks ,在苹果的机器上体验了一下编译 android 系统,说实话,很愉快。 官方没有提到 mavericks 中如何配置环境来编译 android 源代码,幸好还有强大的 xda 。 现在假设现在有一台刚开封的 osx mavericks ,我们将会一步一步配置成可以编译 android 源码。 #1.从苹果商店起步 我们需要从苹果商店下载 xcode5 ,因为我们需要 xcode 给我们带来需要的包和 command line tools 。这个 xcode 很大,小水管拖了几小时才拖了回来。 或者可以点击以下链接下载安装。 Apple Xcode 5 for OS X 10.9 Mavericks #2.安装 Java JDK 6 没错,是安装 JDK 6, 别贪新鲜下个 7 回来,会哭死你的。 下载和安装都很简单,apple 已经为我们准备好 dmg 了,点击以下链接。 Java for OS X 2013-005 #3.安装 Brew 和相关的包 brew 就相当于 ubuntu 的 apt-get ,就算不是为了编译 android 也是程序员必装的软件。 安装 brew 也很简单 ,只要在控制台(Terminal)输入以下命令(除了官方提供的Terminal,强烈推荐iterm2 ) ...

November 9, 2013