模块,客户端

空arraylist占用内存(arraylist为空)

空arraylist占用内存(arraylist为空)

arraylist为空

1. LBS系统架构

LBS系统分为三大部分:

1) 第一部分为LBS客户端管理部分,主要提供给客户端应用使用,客户端应用调用此部分提供的功能进行位置定位。

LocationManager,提供给客户端应用调用,获取位置等信息,同时当有位置信息变化时通知客户端应用。

LocationListener,提供给客户端应用注册使用,每个客户端应用对应一个LocationListener,通过LocationManager注册到系统维护的一个位置服务的链表中,当系统中发现有位置信息变化或者其它信息变化时,会通过它通知客户端应用。

GpsStatus,提供给客户端应用获取GPS定位服务的状态。

GeoCoder,提供给客户端应用调用,获取地理编码信息。

2)第二部分为LBS系统服务部分,开机时启动此服务LocationManagerService,一方面负责处理LBS客户端管理提供的定位等功能需求,另一方面启动提供定位功能的功能模块。

3)第三部分为LBS的定位功能服务部分,完成定位服务模块的定位等动能。

GpsLocationProvider,提供GPS定位服务,通过GPS底层模块获取位置信息及状态变化,通知LBS系统服务来获取位置信息及状态变化等。

LocationProviderProxy,提供网路定位服务,会通过ILocationProvider调用LocationProvider提供的定位功能。LocationProvider只是提供了一个抽象的定位服务模块,并没有真正实现定位功能,需要用户去实现继承LocationProvider来完成此功能。

GeocodeProxy,提供地址编码服务,会通过IGeocodeProvider调用GeocodeProvider提供的正反向地址编码功能。GeocodeProvider只提供了一个抽象的反向地址编码服务模块,根据经纬度来获取地址信息,它并没有真正实现反向地址编码功能,需要用户去实现继承GeocodeProvider来完成此功能。

2. LBS目录结构

(1) frameworks/base/services/java/com.android.server/LocationManager.java

提供的系统定位服务类。

(2) frameworks/base/services/java/com.android.server.location/

提供给系统定位服务使用的相关类。

(3) frameworks/base/location/lib/java/com.android.location.provider/

提供的抽象定位服务模块类以及地址编码服务模块类。供用户继续以实现某种定位功能。

(4) frameworks/base/location/java/android.location

提供给客户端使用的定位服务相关类。

3. LBS定位服务流程

3.1. 启动系统定位服务

开机后由系统启动系统定位服务LocationManagerService。

1) 加载和启动提供定位服务的各个定位模块LocationProviderInterface;

2) 注册网络更新;

3) 注册包管理更新,监听设置变化信息,获取各个定位模块可用信息。

3.2. 客户端应用注册监听

客户端应用实现LocationListener接口,通过LocationManager传递给LocationManagerService一个注册监听器,当定位模块有状态变化或者位置变化等信息变化时,定位模块会通知LocationManagerService,LocationManagerService再通过该监听器把信息变化发给对应的客户端应用,然后客户端应用再进行相应的处理。

1)客户端应用调用LocationManager.requestLocationUpdates(Stringprovider,..., ILocationListener listener);

客户端会实现一个接口LocationListener,封装在ILocationListener中,通过参数传入上面的函数中,进行注册回调。

2)LocationManagerService.getReiver(ILocationListenerlistener);根据ILocationListener生成Receiver,并加入到LocationManagerService维护的一个HashMap<ILocationListener,Receiver>列表中。 当LocationManagerService发现有位置、状态等信息变化时,调用该列表中的各个Receiver,通知客户端应用对应的监听器。

3)LocationManagerService.requestLocationLocked(Stringprovider,…,Receiver receiver);创建一个UpdateRecord(provider,…,receiver,uid),记录客户端监听的记录,存入到LocationManagerService维护的HashMap<String provider, ArrayList<UpdateRecord>>中,记录客户端对每个定位功能模块provider的位置监听记录。

3.3. 系统定位服务通知状态或者位置变化

当LocationMangerService收到定位功能模块传来的状态或位置等信息变化时,会更新保存的状态或者位置信息,同时通知客户端监听器列表中的各个客户端监听器。

以位置变化为例:

1)当定位模块获取到位置信息变化时,调用LocationManagerService.reportLocaiton(Localtion);

2) LocationManagerService通知其它的定位模块LocationProviderInterface去更新位置信息,LocationProviderInterface.updateLocation(Location);

3)取出客户端监听器列表中的各个监听器Receiver,更新位置信息,调用

Receiver.callLocationChangedLocked (Locatlion);

调用客户端提供的回调函数接口:

ILocationListener.onLocationChanged (Location);

4) 客户端应用更新位置信息:

LocationManager.ListenerTransport.onLocationChanged(Location);

调用LocationListener.onLocationChanged(Location);更新客户端应用所需要的位置信息。

4. LBS网络定位

4.1. LBS系统定位服务初始化网络定位服务

1)获取网络定位模块的包名

在LocationManagerService(…) 中

mNetworkLocationProviderPackageName =resources.getString(

com.android.internal.R.string.config_networkLocationProvider);

2)创建和启动网络定位模块

在LocationManagerService._loadProvidersLocked()中,

如果网络定位模块的包名不为空,则:

创建一个LocationProviderProxy(LocationManager.NETWORK_PROVIDER,

mNetworkLocationProviderPackageName, …);

调用addProvider(…),将其加入到LocationManagerService维护的定位模块列表中,以提供具体的定位服务。

3)LocationProviderProxy在创建时,通过调用bindService(…, ServiceConnection, Context.BIND_AUTO_CREATE),启动绑定mNetworkLocationProviderPackageName对应的网络定位服务,与此服务创建一个连接,创建成功后,会执行:

LocationProviderProxy.ServiceConnection.onServiceConnected(ComponentName className,IBinder service),获取网络定位服务模块传过来的调用接口ILocationProvider。

4.2. 网络定位服务的实现和启动

1)实现网络定位模块

LocationProvider为网络定位的基类,外部需要继承并实现它; LocationProvider中创建了一个接口类 ILocationProvider,用于与LBS系统服务交互。

2)启动网络定位模块

LocationProviderProxy启动网络定位服务模块,网络定位服务模块创建LocationProvider,

并与之建立连接; 网络定位服务启动成功后,会传给LocationProviderProxy 已经创建好的ILocationProvider对象。

4.3. 系统定位服务调用网络定位模块

LocationManagerService会调用ILocationProvider的接口函数,进而调用到LocationProvider的函数。

5. LBS地址编码

5.1. 系统定位服务中初始化

1)获取地址编码模块的包名

在LocationManagerService(…) 中

mGeocodeProviderPackageName= resources.getString(

com.android.internal.R.string.config_geocodeProvider);

2)创建和启动地址编码模块

在LocationManagerService._loadProvidersLocked()中,

如果地址编码模块的包名不为空,则:

创建一个GeocoderProxy(mGeocodeProviderPackageName)。

3)GeocoderProxy在创建时,通过调用bindService(…, ServiceConnection, Context.BIND_AUTO_CREATE), 启动mGeocodeProviderPackageName对应的地址编码服务,与此服务创建一个连接,创建成功后,会执行:

GeocoderProxy.ServiceConnection.onServiceConnected(ComponentNameclassName, IBinder service),获取地址编码模块传过来的调用接口IGeocodeProvider。

5.2. 地址编码模块的实现和启动

1)实现地址编码模块

GeocodeProvider为地址编码模块的基类,外部需要继承并实现它;

GeocodeProvider中创建了一个接口类 IGeocodeProvider,用于与LBS系统服务交互。

2)启动地址编码模块

GeocoderProxy启动地址编码模块GeocodeProvider,

并与之建立连接; GeocodeProvider启动成功后,会通过getBinder() 传给GeocoderProxy已经创建好的IGeocodeProvider对象。

5.3. 系统定位服务调用地址编码模块

LocationManagerService中的GeocodeProxy会调用IGeocodeProvider的接口函数,进而调用到GeocodeProvider的函数。

arraylist置空

1 逻辑远比方便重要。

有的人喜欢将主表数据之前,生成细表数据。撇开数据库的主外键约束的情况不说,单单从逻辑上,也应该是先有主表数据,然后再有细表数据。

为了绑定显示方便,而将细表数据先存到数据库中,和逻辑上的混乱与造成的麻烦相比,远远得不偿失。

2 临时数据,临时存。

简单的临时数据,可以存到ViewState当中,复杂的(如发表一个新闻,带多个附件的)可以用Session.

Session可以放置任何对象。Ctype(Session("FJ"),ArrayList)可以存放很多东西,比如FileUpload。一些技巧应用能带来非常多的好处。但是,不要将临时数据存到数据库中。更不要指望用复杂的判断和清除数据、置标识等方式,貌似很有技巧,实际上是把简单的事情复杂了。

3 事务,事务!

主细表数据一个按钮同时添的时候,要有先有后,有事务,出错就回滚。我的习惯如下

Try

DB.StartTrans()

执行SQL1(主表)

执行SQL2(细表)

执行SQL3(细表)

执行SQL4(细表)

....

DB.Commit()

'提示成功

Catch ex As Exception

DB.RollBack()

'将ex信息提示出来

End Try

如果有一些是调用函数内部有Try了。或者某些执行返回影响行数为0,那就在本页面自己手动Throw一些错误,比如

If Myuser.Insert(参数,参数)=0 Then

Throw New Exception "增加人员失败"

End If

由于我的Insert函数中已经Try了,返回值根据是否为0判断是执行否有错误,那么我就手动Throw出相应的信息。

4 约束关系一定要完整

一个好的程序,不仅仅是代码要逻辑清楚,简捷,健壮.同时,对于数据库,其约束,索引,主键,外键一定要完整.一个好的约束,是避免错误数据产生和简化开发最直接有效的办法.

arraylist array

ArrayList可以方便的实现列表操作,但有时候需要建立一个ArrayList数组.首先想到的是类似下面的方法:ArrayList<Integer[]list=newArrayList<Integer()[N];但会出现错误.改为ArrayList[]list=newArrayList[N];会有警告.这是因为Java没有范型数组,可以参考以下方法实现类似功能:ArrayList<ArrayList<Integerals=newArrayList<ArrayList<Integer();ArrayList<Integera1=newArrayList<Integer();ArrayList<Integera2=newArrayList<Integer();ArrayList<Integera3=newArrayList<Integer();

arraylist isempty

stirng指令 是C++里面一个用来处理字符串的类。

包含了字符串处理掉一下常用方法,如:

Constructors 构造函数,用于字符串初始化

Operators 操作符,用于字符串比较和赋值

append() 在字符串的末尾添加文本

assign() 为字符串赋新值

at() 按给定索引值返回字符

begin() 返回一个迭代器,指向第一个字符

c_str() 将字符串以C字符数组的形式返回

capacity() 返回重新分配空间前的字符容量

compare() 比较两个字符串

copy() 将内容复制为一个字符数组

data() 返回内容的字符数组形式

empty() 如果字符串为空,返回真

end() 返回一个迭代器,指向字符串的末尾。(最后一个字符的下一个位置)

erase() 删除字符

find() 在字符串中查找字符

find_first_of() 查找第一个与value中的某值相等的字符

find_first_not_of() 查找第一个与value中的所有值都不相等的字符

find_last_of() 查找最后一个与value中的某值相等的字符

find_last_not_of() 查找最后一个与value中的所有值都不相等的字符

get_allocator() 返回配置器

insert() 插入字符

length() 返回字符串的长度

max_size() 返回字符的最大可能个数

rbegin() 返回一个逆向迭代器,指向最后一个字符

rend() 返回一个逆向迭代器,指向第一个元素的前一个位置

replace() 替换字符

reserve() 保留一定容量以容纳字符串(设置capacity值)

resize() 重新设置字符串的大小

rfind() 查找最后一个与value相等的字符(逆向查找)

size() 返回字符串中字符的数量

substr() 返回某个子字符串

swap() 交换两个字符串的内容

arraylist

ArrayList

1)只能装入引用对象(基本类型要转换为封装类);

2)线程不安全;

3)底层由数组实现(顺序表),因为由顺序表实现,所以会具备顺序表的特点,如:需要声明长度、超出长度时需要进行扩容、不适合频繁的移动删除元素、检索元素快;

4)capacity默认为10,超出时,capacity自动增长0.5倍(oldCapacity >> 1)。

Vector:

1)只能装入引用对象(基本类型要转换为封装类);

2)Vector通过synchronized方法保证线程安全;

3)底层也由数组实现;

4)capacity默认为10(在构造方法中),超出时增长capacityIncrement的量,capacityIncrement小于等于0时,则增长1倍((capacityIncrement > 0) ? capacityIncrement : oldCapacity)。

LinkedList

1)只能装入引用对象(基本类型会转换为封装类);

2)线程不安全;

3)底层实现为链表,具备链表的特点,如:不用声明长度、检索性能较差,但是插入移动删除较快。

4)链表通过Node对象实现。

arraylist存null

ArrayList和LinkedList

共性:ArrayList与LinkedList都是List接口的实现类,因此都实现了List的所有未实现的方法,只是实现的方式有所不同。

区别:List接口的实现方式不同

ArrayList实现了List接口,以数组的方式来实现的,因此对于快速的随机取得对象的需求,使用ArrayList实现执行效率上会比较好。

LinkedList是采用链表的方式来实现List接口的,因此在进行insert和remove动作时效率要比ArrayList高。适合用来实现Stack(堆栈)与Queue(队列)。

HashTable和HashMap

共性:都实现了Map接口。

区别:

(1)继承的父类不同

Hashtable继承自Dictionary类,而HashMap继承自AbstractMap类。

(2)线程安全性不同

Hashtable的方法是Synchronize的,而HashMap中的方法在缺省情况下是非Synchronize的。

(3)提供contains方法

HashMap把Hashtable的contains方法去掉了,改成containsValue和containsKey,因为contains方法容易让人引起误解。

Hashtable则保留了contains,containsValue和containsKey三个方法,其中contains和containsValue功能相同。

(4)key和value是否允许null值

Hashtable中,key和value都不允许出现null值。HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。

(5)两个遍历方式的内部实现上不同

HashMap使用了 Iterator;Hashtable使用 Iterator,Enumeration两种方式 。

(6)hash值不同

哈希值的使用不同,HashTable直接使用对象的hashCode。而HashMap重新计算hash值。

(7)内部实现使用的数组初始化和扩容方式不同

HashTable在不指定容量的情况下的默认容量为11,增加的方式是 old*2+1;而HashMap为16,Hashtable不要求底层数组的容量一定要为2的整数次幂,而HashMap则要求一定为2的整数次幂。