  
- UID
- 1
- 威望
- 1240 点
- 金钱
- 24019 金币
- 点卡
- 317 点
|
所需阅读权限 1 [分享]BREW&J2ME:在差别中联合(2)
[这个帖子最后由cnangel在 2004/05/25 05:48pm 第 1 次编辑]
作者:Radu Braniste什么是List?
包装
前景
源代码下载
原文地址
参考文献
关于作者
什么是List?
BREW不提供List,而是提供MenuCtl。简单的说,“List就是一个暴露MenuCtl功能的IDisplayable。”- template <class T,
- class P=ListStrategy,
- class E = ErrorHandler>
- class ListImpl : public IDisplayable
- {
- typedef bool (T::*FNC)(ListImpl<T,P,E>*);
- public:
- static ListImpl* getList(
- const WString& title, T* t)
- {
- ListImpl* l = createList(t);
- if (l)
- {
- l->setTitle(title);
- l->setFullScreen();
- }
- return l;
- }
- virtual ~ListImpl()
- {
- if (list_) IMENUCTL_Release(list_);
- }
- void append(const WString& item)
- {
- if (!rr_)
- return;
- int id = rr_->getNextAvailableID();
- IMENUCTL_AddItem(list_, 0, 0, id,
- const_cast<AECHAR*>
- (item.toCharArray()), 0);
- indxs_.append(id);
- }
- void append(const WString items[]s, int sz)
- {
- for(int i=0; i < sz; ++i)
- {
- append(items[i]);
- }
- }
- virtual IControl* getControl() const
- {
- return reinterpret_cast<IControl*>(list_);
- }
- bool onCmd()
- {
- if (fnc_ && t_)
- return (*t_.*fnc_)(this);
- return false;
- }
- int getSelectedIndex() const
- {
- return selected_;
- }
- virtual bool containsItem(int ix)
- {
- selected_ = getIDImpl(ix);
- return (selected_ != INDEX_OUT_OF_BOUNDS);
- }
- virtual int getID() const
- {
- return id_;
- }
- void setCbk(FNC f)
- {
- fnc_ = f;
- }
- void setSelection(int id)
- {
- int lid = IMENUCTL_GetItemID(list_, id);
- IMENUCTL_SetSel(list_, lid);
- }
- int size() const
- {
- return indxs_.size();
- }
- void setTitle(const WString& title)
- {
- if (title.length())
- IMENUCTL_SetTitle(list_, NULL, 0, const_cast<AECHAR*>
- (title.toCharArray()));
- }
- private:
-
- ListImpl( T* t, AEECLSID cid ): list_(0), t_(t) , rr_(0),
- shell_(getShell()), selected_(0)
- {
- if (shell_)
- ISHELL_CreateInstance(shell_, cid, (void **)&list_);
- if (!list_)
- {
- E::onMemAllocError(WString(__FILE__),
- WString((long)__LINE__));
- return;
- }
- rr_ = t_->getDisplayable();
- if (rr_)
- id_ = rr_->registerResource(this);
- }
- static ListImpl* createList( T* t, AEECLSID cid =
- AEECLSID_MENUCTL)
- {
- ListImpl* l = new ListImpl( t, cid);
- if (!l->list_)
- {
- delete l;
- return 0;
- }
- return l;
- }
- void setFullScreen();
- int getIDImpl(int ix);
- private:
- IMenuCtl * list_;
- FNC fnc_;
- T* t_;
- DisplayableRegistry* rr_;
- int selected_;
- int id_;
- IShell * shell_;
- BrewVector<int> indxs_;
- };
复制代码 下一个概念就是事件处理。显然,BREW 和Java之间存在的重要差别包括:一个唯一的ID、事件循环机制配对一个固有的,基于监视器的机制。我说“显然”,那是因为机制之间可以自由切换。甚至J2ME可以共享BREW的缺陷——命令听取者的实现与BREW事件循环紧密关联——这个缺陷通常是一个难于维护的、巨大的“转换”。在此之上,听取者是一个类型很差的构造,它暴露一个不得不被用户抛弃的Displayable接口。我们的框架提供一个更安全的方法,它拥有类型安全的、J2SE风格的听取者。例如, ListImpl 类可定义一个听取者:- typedef bool (T::*FNC)(ListImpl<T,P,E>*);
- 实现如下:
- bool myListUsage( List* l)
- {
- int pos = l->getSelectedIndex();
- return (pos == INDEX_OUT_OF_BOUNDS) ?
- false : BuildCommand(pos), true;
- }
- 并且登记如下:
- l->setCommandListener(myListUsage);
复制代码 Java有一个更好的getSelected() 机制来取代传送到IMENUCTL_AddItem 的唯一标志。通过使用普遍存在的DisplayableRegistry,我们可以很容易的实现它,这段时间内产生的唯一标志在内部可作为ID使用。请注意在某些特殊的情况下使用政策可加快ID的检索。
BREW 和Java之间的一个明显差别在于故障处理,基于RTTI的异常处理在BREW中不可用或者使用成本过高。使用setjmp/longjmp 模拟try/catch机制由于销毁自动对象有问题不能直接应用,但是其他的技能是可用的。为了方便,我们将ErrorHandler当作政策——适当提供异常追踪信息的一种方式——来提供。
包装
让我们使用上述技巧从头开始写一个应用程序。
框架封装在cppapp和brewJ2ME内。一个应用就是一个类——与文件MyApp.h 中的Midlet差不多。以下是编写应用的步骤:
1.将 "MyApp.h"包括在cppapp.h之内。
2.创建一个继承于IMidlet 的Midlet 类。
3.将APPLICATION_TYPE 的类型定义为 Midlet。
结果产生的框架为:- class Midlet : public IMidlet
- {
- };
- typedef Midlet APPLICATION_TYPE ;
复制代码 我们的简单应用将处理两个清单,每一个都包含四项——{"1","2","3","4"} 和{"A","B","C","D"}。例如,按下"1,",我们将看到相应的"A," ,按下 "C" 就转换为"3,",以此类推。这种逻辑可嵌入到两个事件处理器内:my14ListUsage和myADListUsage。- class Midlet : public IMidlet
- {
- typedef ListImpl<Midlet> List;
- private:
- bool my14ListUsage( List* l)
- {
- int pos = l->getSelectedIndex();
- return (pos == INDEX_OUT_OF_BOUNDS) ?
- false : BuildADList(pos), true;
- }
- bool myADListUsage( List* l)
- {
- int pos = l->getSelectedIndex();
- return (pos == INDEX_OUT_OF_BOUNDS) ?
- false : Build14List(pos), true;
- }
- List * Init14List()
- {
- List* l = List::getList("List14", this);
- if (!l) return 0;
- l->setCbk(my14ListUsage);
- WString a[] = {"1","2","3","4"};
- l->append(a,SIZE_OF(a));
- return l;
- }
- List * InitADList()
- {
- List* l = List::getList("ListAD", this);
- if (!l) return 0;
- l->setCbk(myADListUsage);
- WString a[] = {"A","B","C","D"};
- l->append(a,SIZE_OF(a));
- return l;
- }
- void BuildADList(int ix )
- {
- if (!lAD_)
- {
- lAD_ =InitADList();
- }
- BuildList(lAD_, ix);
- }
- void Build14List(int ix )
- {
- if (!l14_)
- {
- l14_ = Init14List();
- }
- BuildList(l14_, ix);
- }
- void BuildList(List* l , int ix)
- {
- if (!l || (l->size()-1)<ix) return;
- l->setSelection(ix);
- getDisplayable()->setCurrent(l);
- }
- public:
- virtual bool onStart()
- {
- l14_ = 0;
- lAD_ = 0;
- BuildADList(2);
- return true;
- }
- private:
- List* l14_;
- List* lAD_;
- };
复制代码 我们真正感兴趣的不是代码的明显简化,而是事件处理的透明性。
前景
这个最初的尝试并没有包括重要内容如多-控制屏幕、处理事件而不是处理EVT_COMMAND、以及控制登记过的资源。下一个部分将讨论所有这些内容以及扩展该框架的机制。
相关原版下载例子
|
我是一个呼吸着现在的空气而生活在过去的人
这样的注定孤独,孤独的身处闹市却犹如置身于荒漠
我已习惯了孤独,爱上孤独
他让我看清了自我,还原了自我
让我再静静的沉思中得到快乐和满足
再孤独的世界里我一遍又一遍
不厌其烦的改写着自己的过去
延伸到现在与未来
然而那只是泡沫般的美梦
产生的时刻又伴随着破灭的到来
在灰飞烟灭的瞬间我看到的是过程的美丽
而不是结果的悲哀。。。
|
|