当前位置:文档之家› Android 图片加载性能优化总结

Android 图片加载性能优化总结

Android 图片加载性能优化总结
Android 图片加载性能优化总结

Android 图片加载性能优化总结

一、Android Bitmap加载大尺寸图片优化:

压缩原因:

1.imageview大小如果是200*300那么加载个2000*3000的图片到内存中显然是浪费可耻滴行为;

2.最重要的是图片过大时直接加载原图会造成OOM异常(out of memory内存溢出)

所以一般对于大图我们需要进行下压缩处理

看不懂英文的话木有关系,本篇会有介绍

主要处理思路是:

1.获取图片的像素宽高(不加载图片至内存中,所以不会占用资源)

2.计算需要压缩的比例

3.按将图片用计算出的比例压缩,并加载至内存中使用

官网大图片加载教程(上面网址里的)对应代码就是:

/**

* 获取压缩后的图片

* @param res

* @param resId

* @param reqWidth 所需图片压缩尺寸最小宽度

* @param reqHeight 所需图片压缩尺寸最小高度

* @return

*/

public static Bitmap decodeSampledBitmapFromResource(Resources

res, int resId, int reqWidth, int reqHeight) {

// 首先不加载图片,仅获取图片尺寸

final BitmapFactory.Options options

= new BitmapFactory.Options();

// 当inJustDecodeBounds设为true时,不会加载图片仅获取图片尺寸信息

options.inJustDecodeBounds = true;

// 此时仅会将图片信息会保存至options对象内,decode方法不会返回bitmap 对象

BitmapFactory.decodeResource(res, resId, options);

// 计算压缩比例,如inSampleSize=4时,图片会压缩成原图的1/4

options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);

// 当inJustDecodeBounds设为false时,BitmapFactory.decode...就会返回图片对象了

options.inJustDecodeBounds = false;

// 利用计算的比例值获取压缩后的图片对象

return BitmapFactory.decodeResource(res, resId, options);

}

代码详解:

核心方法是BitmapFactory.decode...(...., options)

...的意思是此外还有一系列的decodeFile/decodeStream等等方法,都是利用options灵活解析获取图片,

只不过解析图片的来源不同罢了,比如网络图片获取,一般就是解析字节流信息然后decode获取图片实例

Options是图片配置信息,参数详细介绍下:

inJustDecodeBounds 是否只解析边界

设为true时去decode获取图片,只会加载像素宽高信息

设为false时decode则会完全加载图片

inSampleSize 压缩比例

比如原图200*300,如果值是2时会压缩成100*150; 是4则图片压缩成50*75最好是2的幂数,比如2 4 8 16 .....

outHeight 图片原高度

outWidth 图片原宽度

其他参数自行研究,这里暂时只用到这几个decodeSampledBitmapFromResource方法内的三段代码对应上面的三步流程难点在于中间那步,压缩比例的计算,官网同样提供了个calculateInSampleSize方法

其中reqWidth和reqHeight是所需图片限定最小宽高值

/**

* 计算压缩比例值

* @param options 解析图片的配置信息

* @param reqWidth 所需图片压缩尺寸最小宽度

* @param reqHeight 所需图片压缩尺寸最小高度

* @return

*/

public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {

// 保存图片原宽高值

final int height = options.outHeight;

final int width = options.outWidth;

// 初始化压缩比例为1

int inSampleSize = 1;

// 当图片宽高值任何一个大于所需压缩图片宽高值时,进入循环计算系统

if (height > reqHeight || width > reqWidth) {

final int halfHeight = height / 2;

final int halfWidth = width / 2;

// 压缩比例值每次循环两倍增加,

// 直到原图宽高值的一半除以压缩值后都~大于所需宽高值为止

while ((halfHeight / inSampleSize) >= reqHeight

&& (halfWidth / inSampleSize) >= reqWidth) {

inSampleSize *= 2;

}

}

return inSampleSize;

}

利用此方法获取到所需压缩比例值,最终获取到压缩后的图片~

以上代码能够看懂的话,下面这段/*扯淡*/可以跳过

逻辑是将原图宽高一半一半的缩减,一直减到宽高都小于自己设定的限定宽高时为止,测试的时候问题来了

原图400*300,我限定值200*150,if满足进入,while循环第一次,400/2/1=200不满足>的条件~结束循环,

最终返回了个inSampleSize=1给我

马丹我限定值正好是原图的一半啊,你应该返回给我2啊~你特么最后返回个1给我,那压缩处理后的图还是400*300!!!

当我将限定值稍微改一下变成195*145稍微降低一点点时~if满足进入,while循环第一次,400/2/1>195满足~

然后压缩比例1*2变成了2,在下一次while循环时不满足条件结束,最后返回比例值2~ 满足压缩预期

官网的这个方法是: 将图片一半一半的压缩,直到压缩成成大于所需宽高数的那个最低值

大于~不是大于等于,所以就会出现我上面那种情况,我觉得方法不是太好= = 能满

足压缩的需求,但是压缩的比例不够准确~

所以最好改成大于等于,如下(个人意见,仅供参考,在实际压缩中很少遇到恰巧等于的这个情况,所以>和>=差别也不大额~看我这扯扯淡就当对计算比例的逻辑加深个理解吧)

while ((halfHeight / inSampleSize) >= reqHeight

&& (halfWidth / inSampleSize) >= reqWidth) {

inSampleSize *= 2;

}

优化:

还是上面例子,如果限定了200*150,而原图是390*290会是个啥情况?

还是第一次while循环,390/2/1结果是195不满足>200的情况,结束循环,比例值为1,最后图片压缩成400*300

虽然压缩一次以后没有满足大于所需宽高,但是和所需宽高很接近啊!!!

能不能做一个获取压缩成最接近所需宽高数的比例值呢?

我也不知道= = 回头可以慢慢研究, 这个"接近"的定义比较模糊,不好掌握~

找了几个有名的图片加载开源框架发现也都没有这种处理- -不知道是这样设计是不需要呢,还是没啥用呢

以上,图片的像素大小已经做了缩放,但是图片的大小除了和像素有关,还和色彩样式有关不同的样式决定了图片单个像素占的字节数

比如,图片默认的色彩样式为ARGB_8888,每个像素占4byte(字节)大小

可以看到一共有四种色彩样式

ALPHA_8 每个像素只要1字节~可惜只能代表透明度,没有颜色属性

ARGB_4444 每个像素要2字节~带透明度的颜色~可惜官方不推荐使用了

ARGB_8888 每个像素要4字节~带透明度的颜色, 默认色样

RGB_565 每个像素要2字节~不带透明度的颜色

默认为ARGB_8888,如果想丧心病狂的继续减少图片所占大小~不需要透明度参数的话,

那就可以把色彩样式设为RGB_565

设置方法是在BitmapFactory.decode..获取图片事例时

修改配置参数的inPreferredConfig 参数

opts.inPreferredConfig = Bitmap.Config. RGB_565 ;

想亲自撸一撸试一试压缩图片了吧?

要注意点问题,如果用res包下图片测试的话,你会发现有图片尺寸有点混乱

那是因为在drawable-*dpi文件夹中的图片会根据对应对应的屏幕密度值不同自动进行一定的缩放,

比如放在drawable-hdpi里的图片,直接不经过压缩BitmapFactor.decode..出来,会发现bitmap的宽高值是原图的2/3,

测试的时候图片记得放在drawable包下(没有的话自己res下新建一个),否则你会被奇怪的宽高值弄凌乱的,具体变化原因参考源代码处理,或者网上搜搜看。还有就是BitmapFactory.decodeStream方法会偶尔解析图片失败(好像是安卓低版本的一个bug),此时推荐做法是将流转换为字节流处理,然后利用decodeByteArray方法获取图片。

二、Android 加载多张图片的缓存处理

一般少量图片是很少出现OOM异常的,除非单张图片过~大~ 那么就可以用教程一里面的方法了

通常应用场景是listview列表加载多张图片,为了提高效率一般要缓存一部分图片,这样方便再次查看时能快速显示~不用重新下载图片

但是手机内存是很有限的~当缓存的图片越来越多,即使单张图片不是很大,不过数量太多时仍然会出现OOM的情况了~

本篇则是讨论多张图片的处理问题

图片缓存的一般处理是

1.建立一个图片缓存池,用于存放图片对应的bitmap对象

2.在显示的时候,比如listview对应适配器的getView方法里进行加载图片的工作, 先从缓存池通过url的key值取,如果取到图片了直接显示,

如果获取不到再建立异步线程去下载图片(下载好后同时保存至图片缓存池并显示)

但是缓存池不能无限大啊~不然就会异常了,所以通常我们要对缓存池进行一定控制

需要有两个特性:

总大小有个限制,不然里面存放无限多的图片时会内存溢出OOM异常

当大小达到上限后,再添加图片时,需要线程池能够智能化的回收移除池内一部分图片,这样才能保证新图片的显示保存

异步线程下载图片神马的简单,网上异步下载任务的代码一大堆,下载以后流数据直接decode成bitmap图片即可

难点在与这个图片缓存池的设计,现在网上的实现主要有两种

1.软引用/弱引用

2.LruCache

-----------------------------------------------------------------------

拓展: java中4种引用分类

强引用

平常使用的基本都是强引用,除非主动释放(图片的回收,或者==null赋值为空等),否则会一直保存对象到内存溢出为止~

软引用 SoftReference

在系统内存不够时,会自动释放部分软引用所指对象~

弱引用 WeakReference

系统偶尔回收扫描时发现弱引用则释放对象,即和内存够不够的情况无关,完全看心情~虚引用

不用了解,其实我也不熟悉

框架基本都比较爱用这个软应用保存图片作为缓存池,这样在图片过多不足时,就会自动回收部分图片,防止OOM

但是有缺点,无法控制内存不足时会回收哪些图片,如果我只想回收一些不常用的,不要回收常用的图片呢?

于是引入了二级缓存的逻辑

即设置两个缓存池,一个强引用,一个软引用, 强引用保存常用图片,软应用保存其他图片~

强引用因为不会自动释放对象,所以大小要进行一定限定,否则图片过多会异常, 比如控制里面只存放10张图片,

然后每次往里面添加图片的时候,检查如果数量超过10张这个阀值,临界点值时,

就移除强引用里面最不常用的那个图片,并将其保存至软应用缓存池中~

整个缓存既作为一个整体(一级二级缓存都是内存缓存~每次显示图片前都要检查整个缓存池中有没有图片)

又有一定的区分(只回收二级缓存软引用中图片,不回收一级缓存中强引用的图片~)

代码实现

软应用缓存池类型作为二级缓存:

HashMap> mSecondLevelCache = new HashMap>();

强引用作为一级缓存,为了实现删除最不常用对象,可以用LinkedHashMap

LinkedHashMap对象可以复写一个removeEldestEntry,这个方法就是用来处理删除最不常用对象逻辑的

按照之前的设计就可以这么写:

final int MAX_CAPACITY = 10; // 一级缓存阈值

// 第一个参数是初始化大小

// 第二个参数0.75是加载因子为经验值

// 第三个参数true则表示按照最近访问量的高低排序,false则表示按照插入顺序排序HashMap mFirstLevelCache = new LinkedHashMap( MAX_CAPACITY / 2, 0.75f, true) {

// eldest 最老的对象,即移除的最不常用图片对象

// 返回值true即移除该对象,false则是不移除

protected boolean removeEldestEntry(Entry eldest) {

if (size() > MAX_CAPACITY) {// 当缓存池总大小超过阈值的时候,将老的值从一级缓存搬到二级缓存

mSecondLevelCache.put(eldest.getKey(),

new SoftReference(eldest.getValue()));

return true;

}

return false;

}

};

每次图片显示时即使用时,如果存在与缓存中,则先将对象从缓存中删除,然后重新添加到一级缓存中的最前端

会有三种情况

1.如果图片是从一级缓存中取出来的,则相当于把对象移到了一级缓存池的最前端(相当于最近使用的一张图片)~

2.如果图片是从二级缓存中取出来的,则会存到一级缓存池最前端并检测,如果超过阀值,则将最不常用的一个对象移动到二级缓存中

3.如果缓存中没有,那就网上下载图片,下载好以后保存至一级缓存中,同样再进行检测是否要移除一个对象至二级缓存中

结合现实例子理解下(如果以上逻辑了解可以跳过):

美国篮球,比如有一个最高水平的联赛NBA,还有一个次一级的联赛NBDL~

一级联赛NBA的排名按最近一次拿冠军的时间由近到远排列,

我们规定,每一季度比赛都要产生一个冠军,冠军可能是已有的任何一个队伍也可能是一个民间来的新队伍~

而当一个队伍获取冠军的时候就给他加到一级队伍NBA里~ 由于是最近一次拿冠军,所以加进去的时候也是排名第一

NBA作为最高水平,我们对数量是有限制的,所以每次有新冠军产生的时候我们都做一次检测,

如果队伍总数量超过20支,那么就移除排名最低即离上次获冠军时间最长的那个最差队伍.

如果每季度比赛拿冠军相当于一次图片使用操作,那上面三种情况就对应我们例子中的: 1.NBA的队伍拿冠军,相当于这个队伍排名变成了第一名~但NBA队伍总数不变,没有新加入来的

2.NBDL二级联赛拿冠军,则加入到NBA里面,且变成了第一名~由于NBA队伍相当于增加了一个,那就要检测一下是否超过20支并将最差成绩的挤到NBDL中

3.民间来大神了虐了全部的队伍拿了冠军,那直接加入NBA然后变成第一名,同样,检测NBA 球队数量判断是否要挤出去一队

NBDL球队相当于软应用的二级缓存池, 不限定数量~ 多少都可以, 直到美国篮联维护全部NBA NBDL球队的资金不够了(相当于图片过多应用内存不足了)

则自动解散一部分球队,落入民间,直到下一次获取总冠军再加入进来(相当于图片从缓存中移除了,下次使用要重新下载)~

那NBA就相当于一级缓存,经常拿冠军(相当于高频率使用的图片),那我们就不想因为资金不足随机解散几个球队恰好就解散了NBA队伍,

则规定资金不够时只解散二级联赛NBDL的队伍~因为他们获取比赛几率低一点~

民间队伍存在与联赛系统之外(相当于不存在缓存中的图片), 而任何一个NBA NBDL联赛球队我们都可以理解为都是民间晋级过来的~

只不过从民间获取总冠军并加入联赛需要一个取名字啊登记啊等等的办手续过程(下载图片),比较麻烦,所以我们要尽可能的少办手续~

而联赛队伍(包括NBA NBDL)获取总冠军则不需要麻烦的手续,可以直接参加比赛去拿冠军(直接获取显示)

两个联赛,一个常用的限定数量,一个不常用的不限定数量,但是资金不足时自动回收部分二级球队~

相当于图片的二级缓存

Disk缓存

可以简单的理解为将图片缓存到sd卡中~

由于内存缓存在程序关闭第二次进入时就清空了,对于一个十分常用的图片比如头像一类的~

我们希望不要每次进入应用都重新下载一遍,那就要用到disk缓存了,直接图片存到了本地,打开应用时直接获取显示~

网上获取图片的大部分逻辑顺序是

内存缓存中获取显示(强引用缓存池->弱引用缓存池) -> 内存中找不到时从sd卡缓存中获取显示-> 缓存中都没有再建立异步线程下载图片,下载完成后保存至缓存中

按照获取图片获取效率的速度,由快到慢的依次尝试几个方法

以文件的形式缓存到SD卡中,优点是SD卡容量较大,所以可以缓存很多图片,且多次打开应用都可以使用缓存,

缺点是文件读写操作会耗费一点时间,

虽然速度没有从内存缓存中获取速度快,但是肯定比重新下载一张图片的速度快~而且还不用每次都下载图片浪费流量~

所以使用优先级就介于内存缓存和下载图片之间了

注意:

sd卡缓存一般要提前进行一下是否装载sd卡的检测, 还要检测sd卡剩余容量是否够用的情况

程序里也要添加注明相应的权限

使用LruCache处理图片缓存

以上基本完全掌握了,每一张图最好再进行一下教程(一)里面介绍的单张缩放处理,那基本整个图片缓存技术就差不多了

但随着android sdk的更新,新版本其实提供了更好的解决方案,下面介绍一下

摘取段对软引用的介绍

Avoid Soft References for Caching

In practice, soft references are inefficient for caching. The runtime doesn't have enough information on which references to clear and which to keep. Most fatally, it doesn't know what to do when given the choice between clearing a soft reference and growing the heap. The lack of information on the value to your application of each reference limits the usefulness of soft references. References that are cleared too early cause unnecessary work; those that are cleared too late waste memory.

Most applications should use an android.util.LruCache instead of soft references. LruCache has an effective eviction policy and lets the user tune how much memory is allotted.

简单翻译一下

我们要避免用软引用去处理缓存

在实践中,软引用在缓存的处理上是没有效率的。运行时没有足够的信息用于判断哪些引用要清理回收还有哪些要保存。

最致命的,当同时面对清理软引用和增加堆内存两种选择时它不知道做什么。

对于你应用的每一个引用都缺乏有价值的信息,这一点限制了软引用让它的可用性十分有限。过早清理回收的引用导致了无必要的工作; 而那些过晚清理掉的引用又浪费了内存。

大多数应用程序应该使用一个android.util。LruCache代替软引用。LruCache有一个有效的回收机制,让用户能够调整有多少内存分配。

简而言之,直接使用软引用缓存的话效果不咋滴~推荐使用LruCache

level12以后开始引入的,为了兼容更早版本,android-support-v4包内也添加了一个LruCache类,

所以在12版本以上用的话发现有两个包内都有这个类,其实都是一样的~

那么这个类是做啥的呢~这里是官方文档

https://www.doczj.com/doc/8a7015146.html,/reference/android/util/LruCache.html

LRU的意思是Least Recently Used 即近期最少使用算法~

眼熟吧,其实之前的二级缓存中的那个强引用LinkedHashMap的处理逻辑其实就是一个LRU 算法

而我们查看LruCache这个类的源代码时发现里面其实也有一个LinkedHashMap,大概扫了眼,逻辑和我们之前自己写的差不多

核心功能基本都是: 当添加进去新数据且达到限制的阀值时,则移除一个最少使用的数据

根据这个新的类做图片加载的话,网上大部分的做法还是二级缓存处理

只不过将LinkedHashMap+软引用

替换成了LruCache+软引用

都是二级缓存,强引用+软引用的结构~因为LruCache和LinkedHashMap都是差不多的处理逻辑

没有移除软引用的使用,而是将两者结合了起来

根据官网的介绍来看其实软引用效果不大,二级缓存的处理的话,虽然能提高一点效果,但是会浪费对内存的消耗~

所以要不要加个软引用的二级缓存,具体选择就看自己理解和实际应用场景了吧

LruCache我理解是牺牲一小部分效率,换取部分内存~我个人也是倾向于只使用LruCache 的实现不用软引用了,也比较简单~

结合前面举得例子可以理解为,直接取消NBDL二级联赛(软引用)~ 这样能省下好大一笔钱(内存)然后投资联赛其他方面(处理其他逻辑)

并扩展下NBA一级联赛(LruCache)的规模~保证复用效率

LruCache的具体用法

之前对LinkedHashMap有了一定了解了,其实LruCache也差不多

类似于removeEldestEntry方法的回收逻辑,在这个类里面已经处理好了

一般我们只需要处理对阀值的控制就行了

阀值控制的核心方法是sizeOf()方法, 该方法的意思是返回每一个value对象的大小size~默认返回的是1~即当maxSize(通过构造方法传入)设为10的时候就相当于限制缓存池只保留10个对象了~

和上面LinkedHashMap的例子一个意思

但是由于图片的大小不一,一般限定所有图片的总大小更加合适,那我们就可以对这个sizeOf 方法进行复写

@Override

protected int sizeOf(String key, Bitmap value) {

return value.getRowBytes() * value.getHeight();

}

这样的话,相当于缓存池里每一个对象的大小都是计算它的字节数,则在新建LruCache的时候传入一个总size值就行了,

一般传入应用可用内存的1/8大小

本篇是讨论对于图片数量的控制问题, 再结合教程(一)中的方法对每一张图片进行相应处理~OOM的情况基本就可以避免了~

内容比较多,有疑惑的地方或者不足的地方大家可以一起探讨

三、Android开源图片框架分析

主要介绍这三个框架,都挺有名的,其他的框架估计也差不多了

Android-Universal-Image-Loader

ImageLoader

Volley(综合框架,包含图片部分)

扯淡时间,可以跳过这段

这些开源框架的源码还是挺复杂的,本人技术有限,有部分分析不对的地方或者不足的地方希望大家一起讨论,

由于有大量的源代码分析,所以造成内容较多且比较杂乱,重点部分我会用红字或者加粗字体标出来,如果没有耐心全部看完的话可以挑部分重点看,可以跳过的部分我也会有说明,大家可以选择性阅读

其实框架的实现和我们教程(一)(二)章的也差不多,只不过在此基础上进行了一些优化,核心部分是几乎没有区别的

由于篇幅有限,暂时只介绍第一个框架(其他其实也都差不多),另外两个在后续教程中详细介绍

首先介绍universal-image-loader(以下简称UIL)

是github社区上star最多的一个项目,可以理解为点赞最多滴,应该是最有名的一个~国内很多知名软件都用它包括淘宝京东聚划算等等

框架其实都差不多,这里详细介绍下使用者最多的一个~之后再分析其他框架时就简单说明一些特性了,重复相似部分不再赘述了~

使用比较简单,这个框架的github主页上也有快速使用的步骤

基本上就是在application类里的oncreate方法(整个程序开始时运行一次)中进行一下简单的基本配置,

可以根据需要自行进行设定,懒得设定的话框架也提供了一个默认的配置,调用一个方法即可基本上是配置一些类似于:缓存类型啊,缓存上限值啊,加载图片的线程池数量啊等等

此外在页面内显示的时候还要设置一个显示配置这个配置不同于基本配置,一个项目里可以根据需要创建多个配置对象使用,

这个配置就比较具体了,可以设置是否使用disk缓存(存到sd卡里一般),加载图片失败时显示的图片,默认图片,图片的色彩样式等

配置好以后,就是简单的使用了,创建一个图片加载对象,然后一行代码搞定显示图片功能~参数一般是入你需要显示的图片url和imageview对象

大部分框架其实都这一个尿性,配置稍微麻烦点,但是使用时一般只需要一行,显示方法一般会提供多个重载方法,支持不同需要~

由于不是框架使用教程,所以~

下面结合之前两章的内容着重分析下框架对于单张图片的压缩处理,和多图缓存池的处理

单张图片的压缩

(业界良心的小技巧: 框架肯定也是基于android sdk的, 所以获取图片缩放实例的

话,option的inSampleSize参数是肯定要使用的, 我们直接crtl+h打开搜索页面,选择file

search, 然后file name patterns选择*.java,即搜索所有java文件,最后在containing text 上输入想搜索的内容,这里我们要搜inSampleSize,搜索结果里随便扫一扫,发现BaseImageDecoder里面有个靠谱的方法如下)

[mw_shl_code=java,true]protected Options prepareDecodingOptions(ImageSize imageSize, ImageDecodingInfo decodingInfo) {

ImageScaleType scaleType = decodingInfo.getImageScaleType();

int scale;

if (scaleType == ImageScaleType. NONE) {

scale = ImageSizeUtils. computeMinImageSampleSize(imageSize);

} else {

ImageSize targetSize = decodingInfo.getTargetSize();

boolean powerOf2 = scaleType == ImageScaleType.IN_SAMPLE_POWER_OF_2 ; scale = ImageSizeUtils. computeImageSampleSize(imageSize, targetSize, decodingInfo.getViewScaleType(), powerOf2);

}

if (scale > 1 && loggingEnabled) {

L. d(LOG_SUBSAMPLE_IMAGE, imageSize, imageSize.scaleDown(scale), scale, decodingInfo.getImageKey());

}

Options decodingOptions = decodingInfo.getDecodingOptions();

decodingOptions. inSampleSize = scale;

return decodingOptions;

}

简单扫一眼,ImageSize,ImageDecodingInfo神马的明显是自定义的一个类,不要管,我们先挑重点部分看

Options decodingOptions = decodingInfo.getDecodingOptions(); decodingOptions.inSampleSize= scale;

方法最后两行可以看出来ImageDecodingInfo类里面保存了一个option对象~

通过一个方法对其中的inSampleSize进行了设置~

ImageScaleType.NONE 什么意思,扫了眼注释,是图片无压缩~那我们看else里面的需要压缩的computeImageSampleSize方法

方法是具体如何处理的呢~ 我们再继续跟踪computeImageSampleSize方法~

(业界良心小技巧:按着ctrl不松左键点击方法或者变量或者类,就可以自动跳转到对应的地方了)

方法的代码如下

/**

* Computes sample size for downscaling image size ( srcSize ) to view size

(targetSize ). This sample

* size is used during

* {@linkplain BitmapFactory#decodeStream(java.io.InputStream, android.graphics.Rect, android.graphics.BitmapFactory.Options)

* decoding image} to bitmap.

*

* Examples:

*

*

* srcSize(100x100), targetSize(10x10), powerOf2Scale = true -> sampleSize = 8

* srcSize(100x100), targetSize(10x10), powerOf2Scale = false -> sampleSize = 10 *

* srcSize(100x100), targetSize(20x40), viewScaleType = FIT_INSIDE -> sampleSize = 5

* srcSize(100x100), targetSize(20x40), viewScaleType = CROP -> sampleSize = 2

*

*

*

* The sample size is the number of pixels in either dimension that correspond to a single pixel in the decoded

* bitmap. For example, inSampleSize == 4 returns an image that is 1/4 the width/height of the original, and 1/16

* the number of pixels. Any value <= 1 is treated the same as 1.

*

* @param srcSize Original (image) size

* @param targetSize Target (view) size

* @param viewScaleType {@linkplain ViewScaleType Scale type} for placing image in view

* @param powerOf2Scale true - if sample size be a power of 2 (1, 2, 4, 8, ...) * @return Computed sample size

*/

public static int computeImageSampleSize(ImageSize srcSize, ImageSize targetSize, ViewScaleType viewScaleType,

boolean powerOf2Scale) {

int srcWidth = srcSize.getWidth();

int srcHeight = srcSize.getHeight();

int targetWidth = targetSize .getWidth();

int targetHeight = targetSize .getHeight();

int scale = 1;

int widthScale = srcWidth / targetWidth;

int heightScale = srcHeight / targetHeight;

switch (viewScaleType) {

case FIT_INSIDE:

if (powerOf2Scale) {

while (srcWidth / 2 >= targetWidth || srcHeight / 2 >= targetHeight) { // || srcWidth /= 2;

srcHeight /= 2;

scale *= 2;

}

} else {

scale = Math. max(widthScale, heightScale); // max

}

break;

case CROP:

if (powerOf2Scale) {

while (srcWidth / 2 >= targetWidth && srcHeight / 2 >= targetHeight) { // && srcWidth /= 2;

srcHeight /= 2;

scale *= 2;

}

} else {

scale = Math. min(widthScale, heightScale); // min

}

break;

}

if (scale < 1) {

scale = 1;

}

return scale;

}

我连注释一起复制过来了,里面对参数有比较详细的介绍,还有对应的例子~很良心的注释啊~

可以看到核心计算方法,其实和我们教程(一)里面是一样的(区别在于这里有两个情况的处理,一个是||一个是&&,后面会介绍原因),对源图的宽高和目标图片的宽高进行一些判断,满足时一直循环下去进行处理,直到取得一个合适的比例值为止,最终保证

使压缩后显示的图片像素密度是大于等于设定的像素密度的那个最低值

(这里换了个更合适的说法,因为框架对图片不同scaleType造成的不同显示效果进行的区别处理,使得压缩比例值计算的更加精确,其实不用这个优化处理已经能够满足图片缩放显示需求了,这里是为了做到更好,当然也会更麻烦了,所以作为我们学习者来说要自行取舍要研究到哪个深度更合适,后面有单独一部分进行介绍,可以选择性看)

框架进行了优化,添加了一个powerOf2Scale的参数和viewScaleType的参数区别不同情

android开发试用期工作总结

android开发试用期工作总结 篇一:android软件开发工程师转正个人总结 个人总结 我于20XX年8月13日进入公司,根据公司的需要,目前担任Android软件工程师一职,负责综合代维,考务通手机客户端的开发工作。将近3个月的时候在这个新的工作环境我收获颇深。开始让我独立完成整个项目,这还是我的第一次,之前在公司是多人完成,过程中也遇到了许多困难,但是都一一解决了,我想这是我最宝贵的经历,通过三个月的不断学习,在项目开发中的不断锻炼以及同事、领导的帮助,我已逐渐融入这个大家庭,个人的工作技能也有了明显的提高,虽然仍有一些不足,但三个月以来我付出了不少,也收获了不少,我感觉自己成长了,也逐渐成熟了。 初到公司,加入了咨询与信息化部,加入了综合代维项目组,我也曾担心自己不知道该怎么与项目组的同事沟通,担心不知道怎么做好工作,但是项目组的前辈们都很亲切,也很耐心的教导我,解答我的疑问,以及他们团结向上的精神,让我很快的熟悉了工作,融入了项目组。 在这三个月的学习和工作中,我一直严格要求自己,遵循公司的规章制度,认真完成领导布置的每一项任务,遇到的问题虚心的向项目组的前辈们学习、请教,不断的提高、

充实自己。开发过程中出现的一些差错,也有前辈们耐心的指出和指导我修改,这些经历让我不断成熟,处理问题时考虑得更全面,杜绝类似情况的发生。在此我要特地感谢部门的领导和同事们对我的指引和帮助,感谢他们对我工作上失误的提醒和指正。 经过这三个月,我已经能独立进行开发任务,按时按质的完成分配的工作任务,当然还有许多不足,开发的经验仍有待提高,编写代码的简洁性和完整性也需要进一步增强,需要不断的继续学习以提高自己的工作能力。 总之,这三个月来我学到了很多,感悟了很多;看到公司的迅速发展,看到部门的同事越来越多,我深深地感到骄傲和自豪,也更加迫切的希望以一名正式员工的身份在这里工作,实现自己的奋斗目标,体现自己的人生价值,和公司一起成长。 我会用谦虚的态度和饱满的热情做好我的本职工作,为公司创造价值,同公司一起展望美好的未来! XX 20XX年11月13日 篇二:研发试用期工作总结 篇一:研发助理试用期总结 时间如白驹过隙,两个月试用期即将结束,在同事们的悉心关怀和指导下,加上自己不懈努力,各方面取得了一定

Android四大组件

Android四大组件 Android开发平台是开放的平台,而位于四层框架顶端的应用开发,必然涉及到Android组件。本文将为大家详细介绍Android组件。 组件(Component),在谈及所谓架构和重用的时候,是一个重要的事情。很多时候都会说基于组件的软件架构,指的是期望把程序做乐高似的,有一堆接口标准封装完整的组件放在哪里,想用的时候取上几个一搭配,整个程序就构建完成了。 在开篇的时候就在说,Android是一个为组件化而搭建的平台,它引入所谓Mash-Up的概念,这使得你在应用的最上层,想做的不组件化都是很困难的一件事情(底层逻辑,好吧,管不了...)。具体说来,Android有四大组件四喜丸子:Activity、Service、Broadcast Receiver、Content Provider。 Activity 做一个完整的Android程序,不想用到Activity,真的是比较困难的一件事情,除非是想做绿叶想疯了。因为Activity是Android程序与用户交互的窗口,在我看来,从这个层面的视角来看,Android的Activity特像网站的页面。 首先,一个网站,如果一张页面都没有,那...,真是一颗奇葩。而一张页面往往都有个独立的主题和功能点,比如登录页面,注册页面,管理页面,如是。 在每个页面里面,会放一些链接,已实现功能点的串联,有的链接点了,刷,跑到同一站点的另一个页面去了;有的链接点了,啾,可能跳到其他网站的页面去;还有的链接点了,恩...,这次没跑,但当前页面的样子可能有所变化了。这些模式,和Activity给人的感觉很像,只不过实现策略不同罢了,毕竟Android这套架构的核心思想,本身就来自源于Web的Mash-Up概念,视为页面的客户端化,也未尝不可。 Activity,在四大组件中,无疑是最复杂的,这年头,一样东西和界面挂上了勾,都简化不了,想一想,独立做一个应用有多少时间沦落在了界面上,就能琢磨清楚了。从视觉效果来看,一个Activity占据当前的窗口,响应所有窗口事件,具备有控件,菜单等界面元素。从内部逻辑来看,Activity需要为了保持各个界面状态,需要做很多持久化的事情,还需要妥善管理生命周期,和一些转跳逻辑。对于开发者而言,就需要派生一个Activity的子类,然后埋头苦干上述事情。对于Activity的更多细节,先可以参见:reference/android/app/Activity.html。后续,会献上更为详尽的剖析。 Service 服务,从最直白的视角来看,就是剥离了界面的Activity,它们在很多Android的概念方面比较接近,都是封装有一个完整的功能逻辑实现,只不过Service不抛头露脸,只是默默无声的做坚实的后盾。 但其实,换个角度来看,Android中的服务,和我们通常说的Windows服务,Web的后台服务又有一些相近,它们通常都是后台长时间运行,接受上层指令,完成相关事务的模块。

Android开发的核心知识

想要学习移动应用的开发,除了必备的知识要掌握好之外,更多的是要掌握一些核心的基础知识,并且是能够起到关键性作用的知识点,必须是要了解清楚,如果你也是在学习Android开发,下面的核心基础或者对你有一定的帮助! 1.ListView的引入 为什么要采用listview?其实是在数据量过于庞大时,传统的存储方式它是会占用机器大量内存,最终导致OOM异常(内存溢出),listview的出现将会是有效的解决这个弊端的出现。 重点来了listview如何使用呢? res/layout布局文件中定义listview src的java代码里面关心控件findviewbyid(R.id.listview); 创建适配器对象,适配器继承baseAdapter接口 2.构造方法 getCount();控制listview的条目数 getView();得到当前条目视图 View.inflate();布局填充器 设置适配器:setAdapter(adapter); 设置listview列表项的点击事件:setOnClickLinsstener();

通知listview更新数据:adapter.notifyDataSetChanged(); 3.对话框的使用 *普通对话框 *单选对话框 *多选对话框 *进度对话框 *进度条对话框 *自定义对话框 布局填充器:Viewview=View.inflate(Context,https://www.doczj.com/doc/8a7015146.html,yout.dialog,null); 核心API:dialog.setView(view); 4.常见的一些适配器的使用 *数组适配器:ArrayAdapter *简单适配器:SimpleAdapter 5.数据库的常见的事务 为什么需要需要定义数据库事务?最主要的还是为了保证多条操作语句同步执行 6.数据库事务执行流程 db.beginTransaction();开启事务 db.setTransactionSuccessful();设置事务执行成功 db.endTransaction();结束事务 7.样式和主题 样式的作用在单独的UI控件上面 主题的作用它是在activity或者application上 以上的这些功能控件、数据库等这些是开发中必备的功能,在开发中只要这些基本的核心知识都掌握了,那么这对你接下里的进一步开发是比较有帮助的。

新Android程序员试用期个人工作总结

新Android程序员试用期个人工作总结 我于xxxx年9月11日成为本公司技术部的一名.net程序员,三个月的试用期转眼就过去了。这段我人生中弥足珍贵的经历,给我留下了精彩而美好的回忆。在这段时间里您们给予了我足够的关怀、支持和帮助,让我充分感受到了领导们“海纳百川”的胸襟,在对您们肃然起敬的同时,也为我有机会成为影响力在线的一员而惊喜万分。 这段时间,在领导和同事们的关怀和指导下,我通过不懈努力,各方面均取得一定的进步,现将我的工作情况做如下汇报: 一、通过理论学习和日常工作积累经验我的各方面有了很大的进步。 刚到公司不久,我便开始负责.NET方面的开发和广告平台开发和维护,刚开始的时候对我来说确实压力很大,因为各方面都还不熟悉,而且与之前的公司相比,节奏也有点快,不过我慢慢的习惯了环境,和同事相处的比较融洽,领导对我也比较关心,在公司里工作就像是在一个幸福的大家庭里一样,我很快喜欢上了这里。 我到公司不久,第一个项目是xxx公司,做这个项目的时候我遇到了几个问题,我在以前公司做的时候没有在这么短的时候完成一个项目的,在效率上提高了我的能力。做这个项目的时候我也遇到了许多以前没有遇到过的问题,我请教同事和朋友,还有借助网络一一解决了难题。 之后,我将B2B广告招商平台进行了改版,开发了xxx智能建站广告平台以及以后的维护工作。

接下来,我又做了一个比较棘手的项目——xxx在线咨询系统。为什么说棘手呢,因为我以前没有做过这方面的项目,而且我问遍了所有认识的朋友,搜遍了网络也没有找到如何解决的方法,之后我翻书籍,接着搜索网络。功夫不负有心人,终于我找到一个聊天室的小例子,但是功能差的太远,于是我把这个示例一点点的研究,从一点也不懂到后来慢慢看懂,从对AJAX技术一无所知到基本熟练运用。接下来我就开始自己开发,到最后终于把它开发了出来,虽然不是很完美,功能不是很强大,但是它是我辛苦的劳动结晶,我相信以后会把它开发的更强大,更完美。 二、明确岗位职能,认识个人技术能力不足。 经过三个多月的工作,虽然完成了一些项目的开发,我的技能也提高了很多,但是感觉我的技术还有待提高,所以我会在以后的工作中更加努力,努力提高自己的技术和各种不足,努力使自己成为一名称职的职员。 三、提出自己努力计划 1、学无止镜,时代的发展瞬息万变,各种学科知识日新月异。我将坚持不懈地努力学习各种技术知识,并用于指导实践。 2、“业精于勤而荒于嬉”,在以后的工作中不断学习知识,通过多看、多学、多练来不断的提高自己的各项技能。 3、不断锻炼自己的胆识和毅力,提高自己解决实际问题的能力,并在工作过程中慢慢克服急躁情绪,积极、热情、细致地的对待每一项工作。 4、努力提高自己的日常交际能力。

Android应用开发基本知识点汇总

Android应用开发基本知识点汇总 Activity 一生命周期 4种状态 running / paused / stopped / killed 生命周期 Activity启动 onCreate -> onStart -> onResume 点Home返回主界面 onPause -> onStop 再次回到原Activity onRestart -> onStart -> onResume 退出Activity onPause -> onStop -> onDestroy 进程优先级前台/可见/服务/后台/空 二任务栈 三启动模式 standard singleTop 栈顶复用 singleTask 栈内复用 singeInstance 四scheme跳转协议 服务器可以定制化告诉App跳转哪个页面,可以通过通知栏消息定制化跳转页面,可以通过H5页面跳转页面 Fragment 一第五大组件 为什么是第五大组件 Fragment相对Activity更节省内存,切换更舒适Fragment加载到Activity的两种方式 静态加载xml 动态加载fragmentTransaction.add(id, fragment, “name”); .commit; FragmentPagerAdapter与FragmentStatePagerAdapter

FragmentStatePagerAdapter在切换时回收内存,适合页面较多的情况FragmentPagerAdapter并没有回收内存,只是detach了Activity 二生命周期 onAttach -> onCreate -> onCreateView -> onViewCreated -> onActivityCreated -> onStart -> onResume -> onPause -> onStop -> onDestroyView -> onDestroy -> onDetach 先创建Activity后创建Fragment,先销毁Fragment后销毁Activity 三Fragment之间的通信 Fragment调用Activity getActivity Activity调用Fragment 接口回调 Fragment调用Fragment方法findFragmentById 四FragmentManager replace add remove Service 一应用场景,与Thread区别 Service是什么后台长时间运行,没有用户界面,运行在主线程,不能有耗时操作 Service与Thread区别 Activity难以与Thread交互,尤其当Activity销毁以后 二开启Service的两种方式 StartService onCreate -> onStartCommand -> onBind -> onDestroy onStartCommand return START_STICKY;

如何在android程序中显示图片

我们做Android 程序的时候,有时候需要显示图片在界面上,这里我们将实现一个将图片展示到手机屏幕,并让其不停的浮动的效果! 首先我们要先准备一张图片,在这里我准备了一张图片,如下: 将此图片放到文件夹"res->drawable-*dpi"下,记得,三个文件夹都要放,因为系统会根据不同的分辨率去取不同的图片,如果有的没放,在某些分辨率下,会找不到资源。将此图片重命名为“pic.png”,在R.java里的drawable 类里会生成一个pic的常量。 图片要显示,就是要容器可以让其显示,因为所有的Android的UI组件都是继承自View,View也实现了Drawable接口,所以在此,我们也重新定义一个View让其用来显示我们的这张图片,并让这张图片浮动。我们创建一个在包“org.leo.bitmap”下的,类名为“MovingPictureView”的类,该类继承自android.view.View。此类目前代码大致如下: public class MovingPictureView extends View { public MovingPictureView(Context context) { super(context); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); } } 我们要重载他的“onDraw”方法,这个方法就是Android框架展现View的时候用来绘制显示内容那个的方法。在此我们将他的所有方法体都删除掉(上面代码红色部分删掉),完全将其重写。首先我们要创建一个图片对象,在Android里,所有位图图片都是使用Bitmap类来封装的,我们就先声明一个代表我们刚才图片的一个Bitmap对象,可通过以下方式声明: Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.pic); 其中的“getResources()”方法,是有View提供的,可以根据此方法获得我们所有的资源,将来有机会再细说!

android程序员试用期工作总结(最新版)

android程序员试用期工作总 结(最新版) The work summary can correctly understand the advantages and disadvantages of the past work; it can clarify the direction and improve the work efficiency. ( 工作总结) 部门:_______________________ 姓名:_______________________ 日期:_______________________ 本文档文字可以自由修改

android程序员试用期工作总结(最新版) 【篇一】 我于xxxx年9月11日成为本公司技术部的一名.net程序员,三个月的试用期转眼就过去了。这段我人生中弥足珍贵的经历,给我留下了精彩而美好的回忆。在这段时间里您们给予了我足够的关怀、支持和帮助,让我充分感受到了领导们“海纳百川”的胸襟,在对您们肃然起敬的同时,也为我有机会成为影响力在线的一员而惊喜万分。 这段时间,在领导和同事们的关怀和指导下,我通过不懈努力,各方面均取得一定的进步,现将我的工作情况做如下汇报: 一、通过理论学习和日常工作积累经验我的各方面有了很大的进步。 刚到公司不久,我便开始负责.NET方面的网站开发和广告

平台开发和维护,刚开始的时候对我来说确实压力很大,因为各方面都还不熟悉,而且与之前的公司相比,节奏也有点快,不过我慢慢的习惯了环境,和同事相处的比较融洽,领导对我也比较关心,在公司里工作就像是在一个幸福的大家庭里一样,我很快喜欢上了这里。 我到公司不久,第一个项目是xxx公司网站,做这个项目的时候我遇到了几个问题,我在以前公司做的时候没有在这么短的时候完成一个项目的,在效率上提高了我的能力。做这个项目的时候我也遇到了许多以前没有遇到过的问题,我请教同事和朋友,还有借助网络一一解决了难题。 之后,我将B2B广告招商平台进行了改版,开发了xxx智能建站广告平台以及以后网站的维护工作。 接下来,我又做了一个比较棘手的项目——xxx在线咨询系统。为什么说棘手呢,因为我以前没有做过这方面的项目,而且我问遍了所有认识的朋友,搜遍了网络也没有找到如何解决的方法,之后我翻书籍,接着搜索网络。功夫不负有心人,终于我找

Android程序设计教程教学大纲

《Android 程序设计课程》课程教学大纲 一、课程基本信息 二、理论教学内容及基本要求

1 Android 操作系统 本章主要对Android 的发展、特点、环境搭建和体系结构进行简要介绍。并且讲解了JDK、Eclipse、Android SDK 软件的下载及安装的基本知识。对Android 应用程序进行解析,提高读者对程序的创建、目录的结构、资源的管理以及对程序权限的理解。最后讲解如何调试Android 程序。 2 Android 生命周期与组件通信 本章主要讲述了Android 生命周期和组件之间的通信。生命周期主要讲述了Android四大组件之一的Activity 生命周期, 包括生命周期函数、栈结构和基本状态三方面。组件的通信靠Intent 实现, 以及Intent 基本构成。 3 Android 用户界面设计 本章主要从Android 用户界面开发出发, 讲述了开发过程中经常使用到的控件, 包括菜单、常用基础控件、对话框与消息框。界面中控件的结构及位置等需要通过有效的界面布局控制, Android 中提供了5 种界面布局格式, 即线性布局、相对布局、表格布局、绝对布局和框架布局。界面中还有一种必要的操作处理———外部操作的响应, 通过有效的事件机制完成。 4 Android 数据存储与交互 本章主要讲述了Android 数据存储与交互方面的内容, 系统中数据交互主要通过五种方式实现, 共享优先数据机制、SQLite 数据库、File 文件机制、内容提供器控件和网络存储。其中在应用程序中最常用也是最有效的数据交互方式是使用SQLite 数据库。 5 Android 后台服务与事件广播 本章主要讲述了Android 后台服务、事件广播和常驻程序。后台服务由系统提供的Service 组件实现, 可分为本地服务和远程服务。事件广播机制主要依靠BroadCast Reciver 组件实现。常驻程序AppWidget又称为窗口小部件, 是在HomeScreen上显示的小部件, 开发时常用AppWidgetProvider 和AppWidgetProviderInfo 类实现。 6 媒介与网络 本章介绍了Android 平台下通过程序实现音频、视频播放等操作。分别介绍了从源文件播放、文件系统播放和流媒体播放等方式。并且介绍了Android 图形绘制与特效, 包括图形的平移、旋转及缩放等操作, 保存指定格式图形文件。编写专业的绘图或控制图形动画的应用程序。以及如何使用Android 手机中内置的高性能WebKit 内核浏览器浏览网页, 使用HTTP 和URL 获得网络资源等内容。 7 Android NDK 本章介绍了Android NDK 的相关知识, 从NDK 的简单介绍到开发环境的

如何用Android用ImageView显示本地和网上的图片说明

如何用Android用ImageView显示本地和网上 的图片说明 Android:ImageView如何显示网络图片 本文地址:https://www.doczj.com/doc/8a7015146.html,/programmar/blog/item/79483ecb2ac75cf552664fd3.html在 Android中显示一张网络图片其实是超级简单的,下面就一个非常简单的例子: Step1: 1、创建你的Activity,本例中以ViewWebImageActivity说明; 2、ViewWebImageActivity中的代码如下: String imageUrl = "https://www.doczj.com/doc/8a7015146.html,/baidu/pic/item/7d8aebfebf3f9e125c6008d8.jpg"; //这就是你需要显示的网络图片---网上随便找的 Bitmap bmImg; ImageView imView; Button button1; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(https://www.doczj.com/doc/8a7015146.html,yout.main); imView = (ImageView) findViewById(R.id.imview); imView.setImageBitmap(returnBitMap(imageUrl)); } public Bitmap returnBitMap(String url) { URL myFileUrl = null; Bitmap bitmap = null; try { myFileUrl = new URL(url); } catch (MalformedURLException e) { e.printStackTrace(); } try { HttpURLConnection conn = (HttpURLConnection) myFileUrl.openConnection(); conn.setDoInput(true); conn.connect();

(带答案)Android复习资料

选择题 1. 下面不是Android四大组件之一的(B ) A. Activity B.Intent C. Service D. ContentProvider 2. 下面关于广播叙述错误的是(A) A. 广播是Android四大组件之一 B. BroadcastReceiver有两种注册方式,静态注册和动态注册 C. 静态注册需要在Mainfest.xml中配置 D. 动态注册需要在应用退出时候接触广播的注册。 3. 下面关于BroadcastReceiver错误的是(B): A. BroadcastReceiver有两种注册方式,静态注册和动态注册。 B. BroadcastReceiver必须在AndroidMainfest文件中声明 C. BroadcastReceiver的使用,一定有一方发送广播,有一方监听注册广播,onReceive方法才会被调用。 D. 广播发送的Intent都是隐式启动。 4. 下面关于谁先接收广播顺序错误的是(B) A. 有序广播,优先级高的先接收 B. 有序广播,同优先级的动静态广播接收器,静态优先于动态。 C. 有序广播,同优先级的动态广播接收器,先注册的大于后注册的。 D. 普通广播时,无视优先级,动态广播接收器优先于静态广播接收器 5. 下面关于广播说法错误的是(B) A. 广播分为有序广播和无序广播 B. 使用abortBroadcast方法可以中断所有广播的传递。 C. 广播注册方式分为动态和静态

D. sendOrderBroadcast用来向系统广播有序事件,sendBroadcast()是用来广播无序事件。 6. 下列关于Intent启动组件说法错误的是(C) A.startActivity( ) B. startService( ) C. startBroadcastReceiver() D.startActivityForResult() 7. 对于广播的发送,Intent的启动方式是(B) A.显式启动 B. 隐式启动 C. A和B都可以 D. 以上说法都不正确。 8. 下面关于Notification的说法正确的是(D): A. NotificationManager man = new NotificationManager(); B. PendingIntent contentIntent= new PendingIntent(); C. RemoteViews contentView = new RemoteViews(); D. Notification notification = new Notification(); 9. 关于ContenValues类说法正确的是( A ) A、他和Hashtable比较类似,也是负责存储一些名值对,但是他存储的名值对当中的 名是String类型,而值都是基本类型 B、他和Hashtable比较类似,也是负责存储一些名值对,但是他存储的名值对当中的 名是任意类型,而值都是基本类型 C、他和Hashtable比较类似,也是负责存储一些名值对,但是他存储的名值对当中的 名,可以为空,而值都是String类型 D、他和Hashtable比较类似,也是负责存储一些名值对,但是他存储的名值对当中的名是String类型,而值也是String类型 10.在手机开发中常用的数据库是(A) A,SQLite3 B,Oracle C,Sql Server D,Db23

复习材料《Android移动应用开发技术》

1、关于android进程,说法不正确的是( B ) A、组件运行所在的进程,是由androidManifest.xml决定,它可以指定该组件运行于哪个进程。 B、背景进程是不为用户所见的Activity,但是还会有可能被用户看到,所以它不能被杀死 C、当急需内存时,android会决定优先关闭那些空闲的进程 D、可视进程一般不会不被系统所杀死 2、Matrix类的作用( A ) A、可以存储缩小或放大比列 B、存储文件中的图片信息 C、存储资源中的图片信息 D、存储内存中的图片信息 3、关于主题的说法,错误的是( D ) A、它是属性集合 B、它可以在程序中来设置 C、它通常用于一个Activity或所有Activity上 D、它可以用于单个TextView上 4、setOnTouchEvent 设置返回值为true 和 false有何区别?以下说法较准确是( C ) A、没有区别,都能对事件进行监听 B、设置为true时只能在移动时获得一次监听事件,false则可以多次 C、设置为false是,在处理一次监听事件后,系统将抛弃该次事件 D、返回true表示这个消息已经被处理结束,后续的handler不再接收到这个消息 二、开发技术设计与应用能力部分 注:以下程序均是相关程序或小项目的实现代码,根据每个程序或项目的特性,完成程序空缺部分的内容,使其实现。具体程序代码注释省略。 图1 图2 图3 图4 1)电话实现[主界面如图1] 程序描述:完成手机打电话功能。 public class MainActivity extends Activity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(https://www.doczj.com/doc/8a7015146.html,yout.activity_main); Button btn_call = (Button)this.findViewById(R.id.btn_call); btn_call.setOnClickListener(new btnCall()); } private class btnCall implements OnClickListener (1) { public void onClick(View v) { // TODO Auto-generated method stub EditText et_number = (EditText) MainActivity.this.findViewById(R.id.et_number); String s_number = et_number.getText().toString().trim(); (2) Intent i_call = new Intent(); i_call.setAction(Intent.ACTION_CALL(3)); i_call.setData(Uri.parse("tel:"+s_number)); startActivity(i_call); (4) } } } 2)动画实现[主界面如图2] 程序描述:手机屏幕触摸后演示动画,假设XML文件已经设置好,id资源为:R.drawable.panda public class MainActivity extends Activity { ImageView iv_action; AnimationDrawable ad_action; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(https://www.doczj.com/doc/8a7015146.html,yout.activity_main); iv_action = (ImageView)this.findViewById(R.id.iv_action); iv_action.setBackgroundResource(5)(R.drawable.panda); ad_action = (AnimationDrawable) iv_action.getBackground(); } public boolean onTouchEvent(MotionEvent event) { ad_action.start();(6) return super.onTouchEvent(event); } } 3)撕衣服游戏实现 项目描述:划动屏幕时完成撕衣服效果,并产生撕衣服声音(sound.mp3) public class MainActivity extends Activity { ImageView iv_upper; ImageView iv_below;

android 图片剪裁

1. Canvas类用来实现绘制.通过组合使用Canva s类的成员函数可以实现随心随欲地绘制图片的任何部分. Canvas.clipRect:设置显示区域 Canvas.drawBitmap:绘制 例子: Bitmap b=Bitma pFactory.decodeStream("图片编号", null);//读取图片 ... Canvas c = null;//实例Canvas c.save();//记录原来的ca nvas状态 c.clipRect(100,100,200,300);//显示从(100,100)到(200,300)的区域(单位:象素) c.drawBitmap(b,10,0,null); //将阉割过的图片画到(10,0)位置 c.restore();//恢复canva s状态 2. android 从sdcard 读取图片剪切粘贴 文章分类:移动开发 android 图片编辑时需要从外界(sdcard ,res/.png...,xml)读取图片到画布,其中从sdcard读取图片到画布的过程如下: public void drawBitMapFromSDcard(String dir) { if(dir ==null || dir.equals("")){ return ; } bitMap = BitmapFactory.decodeFile(dir); int width = bitMap.getWidth(); int height = bitMap.getHeight(); 如果图片像素太大超过手机屏幕大小可以按照手机屏比例进行缩放 if (width > 320 && height > 480) { int newWidth = 320; int newHeight = 480; float scaleWidth = ((float) newWidth) / width; float scaleHeight = ((float) newHeight) / height; float minScale = Math.min(scaleWidth, scaleHeight); matrix = new Matrix();

程序员个人年终工作总结5篇

程序员个人年终工作总结5篇 #程序员工作总结1# 光阴如梭,半年的工作转瞬即将成为历史,伴随着新年钟声的临近,我们依依惜别硕果累累的20_年,满怀热情的迎来即将到来的20__年。在这年终之际,现对来公司一年来的时间里所作的工作汇报如下: 1、正义erp项目的编码工作。了解新疆正义项目的背景、及计划安排,熟悉正义公司制度及业务流程,再到熟悉新能开发模式,之后我根据需求调研报告,从基本的数据库创建,到编码,完成了销售部、生产部、采购部、质检部四个模块的基本单据的制单、审核、选单、查询、打印等系列的编码工作;完成了正义项目的模块测试及流程测试。 通过这段时间的努力,使我个人的耐心、细心程度及对工作的合理安排得到了锻炼,学会了在繁忙之中找条理,危难之中找希望。同时自己也有一些不足之处,一些细节地方技术上还不太成熟,还需加以学习与钻研。 2、、正义erp项目的实施工作。从十一月初开始进行正义项目的实施,每天早起赶在企业上班前赶到企业进行erp的实施。实施期间

主要是软件的安装实施及对企业的erp系统的使用人员进行软件使用培训;纪录客户使用过程中出现的问题,晚上下班后加班加点将每天的小错误及客户变更修改完毕。 通过这项工作,使我原本欠缺的业务能力得到了很大的提高,并学到了很多与客户交流的技巧及业务上的知识,更加明晰了erp系统的流程。但离一个成功程序开发人员的标准还差得很远,在今后工作中,定会多多注意,加以改善。 3、帮助和使用手册文档的编写。帮助的编写使我熟悉了dreameweaver和fireworks的使用,为后期的oa开发也奠定一定的基础,使用说明的编写,使我更加加深了项目开发的整体思路与技术要点,总结了前期开发和实施中碰到的问题,并又一次的对软件整体进行了测试,对暴露出的小bug进行了最后的修改。 4、利用工作之余的休息时间加强学习。平时注意收集有关pb方面的资料文件,提高自己的处理新问题和解决新问题的能力,并加强学习java及oa方面的知识,为后期的工作打好基础。 以上为本人粗略的个人工作小结,请领导审阅,如工作上有不到之处,请领导不吝指出,以便本人及时改正,从而能更好地工作。 展望临近的20__年,我会更加努力、工作上认真负责,再接再厉,更上一层楼。相信自己会完成新的任务,能迎接新的挑战。

Android基础应用课程标准

《Android基础》课程标准 一、课程定位 本课程是计算机专业基于Java方向的Android应用层程序开发的一门专业核心课程。作为Java程序设计、数据库原理与应用等课程的后续课程,主要在于培养学生应用Android技术进行Android应用程序开发的能力,并培养其良好的编程规范和职业习惯。 二、课程目标 通过案例驱动的学习和综合训练,熟练掌握Android应用程序开发的基本知识和技能,并能结合Android中的常用控件和四大系统组件进行Android应用程序的开发,并为后续Android高级知识的学习做下铺垫。在课程的学习中,培养诚实、守信、坚韧不拔的性格,培养善于沟通表达、善于自我学习、具备团队协作的能力。并养成规范的编码、按时交付软件等良好的工作态度。 (一)知识目标 1.掌握Android开发环境的搭建;熟悉Android应用的基本框架,了解Activity、layout的关系; 2.指导学生进行需求分析报告的拟定以及实训报告的编写; 3.熟练掌握Android常用的UI组件的用法,熟练使用Android的UI组件来搭建用户界面;掌握Android 中用户事件处理的基本方法; 4.掌握APP系统分层架构的搭建; 5.熟练掌握AdapterView相关UI组件以及Adapter模式、常见Adapter的定义; 6.熟悉Activity、Service和BroadcastReceiver的生命周期方法,熟练掌握它们的用法 7.熟悉Intent的用法,熟练使用Intent的诸多属性用途及用法; 8.熟练掌握Service与广播机制的使用和工作原理,为应用开发打下基础; 9.掌握SQLite的语法,熟练掌握Android SQLite 数据库的使用。能够用多种方式实现数据存储和数据 共享; 10.掌握Android的异步加载机制; 11.了解自定义控件的实现原理并掌握自定义技巧。 12.了解Android应用程序的屏幕适配、国际化方式及APP上架流程和盈利方式。 (二)职业能力目标

ANDROID实训心得体会

项目总结 时间过的好快,为期三个月的实训生活即将结束了,每一次的实训我们都受益匪浅,我 们学到的不仅仅是课内还有课外,实训让我们的课内知识得到了巩固,专业知识、编程水平 都有很大的提高,我们非常感谢这次实训。 刚开始二周的高强度的课程安排让我们受益匪浅;接下来的项目实训又让我们可以巩固 了课程。这让我觉得实习生活充实而有意义。 乐淘购物项目和android优化大师,我更好的学习了ui的设计,如何使界面漂亮,美观, 巩固了listview,gridview,的使用,学会了动画进入界面的,和会移动的画廊等等。在这 两个项目中,除了让我明白工作中需要能力,素质,知识之外,更重要的是学会了如何去完 成一个任务,懂得了享受工作。当遇到问题,冷静,想办法一点一点的排除障碍,到最后获 取成功,一种自信心由然而生,这就是工作的乐趣。有时候也需要虚心请教,从别人的身上 真得能学习到不自己没有的东西,每一次的挫折只能使我更接近成功。 音乐播放器项目,我们是七个人组成小组完成的,由组长带领我们,分配任务,每个人, 都发挥自己的长处,更好地去完成任务。对于团队开发来说,团结一致使我深有体会。团队 的合作注重沟通和信任,不能不屑于做小事,永远都要保持亲和诚信,把专业理论运用到具 体实践中,不仅加深我对理论的掌握和 运用,还让我拥有了一次又一次难忘的开发经历,这是也是实训最大的收获。 这次实训对于我以后学习、找工作也真是受益菲浅,在这3个月中让我初步从理性回到 感性的重新认识,也让我初步的认识这个社会,对于以后做人所应把握的方向也有所启发! 相信这些宝贵的经验会成为我今后成功的重要的基石。在此,我非常感谢指导老师和 同学对我的帮助。篇二:android实训报告 通信与电子信息专业实训报告 项目名称:基于android的游戏开发 班级 10通信1班 姓名 学号 指导教师 成绩 实训时间:年月日— 目录 一、实训目的及其意义 (3) 1.1、目的及意义 (3) 1.2、研究现状 (3) 二、实训主要任务、重点及难点 (4) 2.1、任务 (4) 2.2、重点内容及实现途径 (4) 三、实训具体内容及完成的主要工作 (5) 3.1、认识基础开发 (6) 3.2、了解数据存储 (6) 3.3、总体实训过程 (7) 四、实际遇到的困难,解决问题的方法和措施 (8) (一)、所遇问题 (8) (二)、解决方法与措施 (9) 五、心得体会 (9)

android图片3d旋转

看到很多人在问如何实现三维的翻转效果,所以今天在这里简单的给大家分析一下,其实在APIDemo中就有这样一个例子,那么我们就以其为例来学习Android中的翻转动画效果的实现,首先看一下运行效果如下图所示。 Android中并没有提供直接做3D翻转的动画,所以关于3D翻转的动画效果需要我们自己实现,那么我们首先来分析一下Animation 和Transformation。 Animation动画的主要接口,其中主要定义了动画的一些属性比如开始时间,持续时间,是否重复播放等等。而Transformation中则包含一个矩阵和alpha值,矩阵是用来做平移,旋转和缩放动画的,而alpha值是用来做alpha动画的,要实现3D旋转动画我们需要继承自Animation类来实现,我们需要重载getTransformation和applyTransformation,在getTransformation中Animation会根据动画的属性来产生一系列的差值点,然后将这些差值点传给applyTransformation,这个函数将根据这些点来生成不同的Transformation。下面是具体实现: 1.public class Rotate3dAnimation extends Animation { 2.//开始角度 3. private final float mFromDegrees; 4.//结束角度 5. private final float mToDegrees; 6.//中心点

7. private final float mCenterX; 8. private final float mCenterY; 9. private final float mDepthZ; 10.//是否需要扭曲 11. private final boolean mReverse; 12.//摄像头 13. private Camera mCamera; 14. public Rotate3dAnimation(float fromDegrees, float toDegrees, 15. float centerX, float centerY, float depthZ, boolean reverse) { 16. mFromDegrees = fromDegrees; 17. mToDegrees = toDegrees; 18. mCenterX = centerX; 19. mCenterY = centerY; 20. mDepthZ = depthZ; 21. mReverse = reverse; 22. } 23. 24. @Override 25. public void initialize(int width, int height, int parentWidth, int par entHeight) { 26. super.initialize(width, height, parentWidth, parentHeight); 27. mCamera = new Camera(); 28. } 29.//生成Transformation 30. @Override 31. protected void applyTransformation(float interpolatedTime, Transformat ion t) { 32. final float fromDegrees = mFromDegrees; 33.//生成中间角度 34. float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interp olatedTime); 35. 36. final float centerX = mCenterX; 37. final float centerY = mCenterY; 38. final Camera camera = mCamera; 39. 40. final Matrix matrix = t.getMatrix(); 41. 42. camera.save(); 43. if (mReverse) { 44. camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime); 45. } else {

相关主题
文本预览
相关文档 最新文档