如何提升自己
开源意识
,开放平台
思想- Libraries for developersV3.39:众多开源效果集合–>国外–>只是提供了地址
- android开源项目汇总:众多开源效果集合–>国人–>只是提供了地址
baseAnimation:众多开源效果–>针对动画效果–>国人–>开源的.需要效果的时候.要自行去找对应的代码
http://www.23code.com/–>开源项目集合网站
http://a.code4app.com/–>开源项目集合网站
一些demo的集合–>5000
- http://apistore.baidu.com/astore/classificationservicelist/23.html
- https://github.com/Trinea/android-open-project
- http://apistore.baidu.com/
- http://www.androiddevtools.cn/
- http://www.codekk.com/open-source-project-analysis
http://wiki.jikexueyuan.com/project/android-weekly/issue-179/index.html
群里面经常讨论的一些技术
uil imageloder square/picasso 图片加载 square/okhttp 网络请求 square/retrofit 网络请求 greenrobot/EventBus 事件控制 facebook/fresco 图片加载 JakeWharton/butterknife ioc注入 bumptech/glide 图片加载 google公司搞出来的
深度理解
,广度知道
Volley
回忆xutils:
快速开发型框架
,DbUtils(orm),ViewUtils(ioc),HttpUtils,BitmapUtils其他的快速开发型框架:andBase,thinkandroid,loonandroid,dhroid
- orm:对象关系型映射
- db:create table t_table(_id integer primary key autoincret…);
- insert–>save(obj)
- ioc:控制反转
- Obj obj = new Obj();
- 对象的实例化,不用new关键字就可以了吧.
- 为什么要讲volley?
- 因为它是google出的,google 在2013 i/o大会上提出来的.
- 而且在几个项目里面已经看到了它的身影
google公司为什么会去搞一个volley框架?
1.用户开启一个activity,然后加载网络,这个时候.如果用户点击了finish按钮.activity被销毁了–>网络请求和activity的生命周期是应该联动起来的.
2.listview加载图片的情况比较多.如果用户快速的去滑动listview–>getView->快速的加载图片,用户停止操作的时候.其实真正现实的图片最多就几张—>图片应该缓存起来(内存 +本地 )
3.如果用户打开了一个activity,用户旋转了一下屏幕.activity会旋转–>生命周期重走了–>网络请求缓存
4.之前我们的网络请求,httpurlconnection,httpclient,asynctask(api)–>android sdk–>封装性不够好.1000个开发者就有1000种使用方式–>不够统一
- 5.理念很容易理解,是开源的.
- volley是啥?
- 是一种
通信框架
,和xutils中的HttpUtils,BitmapUtils
- 是一种
Volley两个核心类
- Request:一个请求
- StringRequest:请求的时候直接回来一个String
- JsonObjectRequest:请求的时候直接回来一个JsonObject
- JsonArrayRequest:请求的时候直接回来一个JsonArray
- ImageRequest:请求的时候直接回来一个Bitmap
- 自定义请求:一会我们会结合gson
- ImageLoader:图片的加载器
- NetWorkImageView:继承了imageView,对ImageView进行了拓展
- RequestQueue:请求队列.
一步一步学习
JsonObject取值
- String origin = response.getString(“origin”);// 方式一
- 这个如果没有对应的key会抛异常.需要异常处理
- String origin = response.optString(“origin”);// 方式二
- 这个如果没有对应的key不会抛异常.会返回一个默认值
- optString:默认值”“
- optInt:默认值 0
- 比如有的实体bean属性很多.我们不喜欢去建议对应的XXX.class的时候.可以使用JsonObject里面的这个方法;
图片
大图片的处理:
- 大图片处理的核心
- 核心类:BitmapFactory.Options
核心方法:
- decodeOptions.inJustDecodeBounds = true;–>得到图片的宽度以及高度,不需要把图片加载到内存 10M
- decodeOptions.inJustDecodeBounds = false;–>真正去加载图片
- decodeOptions.inSampleSize–>采样率–>不同的框架有不同的核心算法
- 特点:2 4 8 –>取值最好使用2的指数,如果是2,最终效果是1/2*1/
步骤
1.得到实际的宽度和高度
2.得到理想的宽度和高度
3.根据理想的宽度和高度和实际的宽度和高度计算出最好的采样值(inSampleSize)
- 图片的加载
- 图片的缓存
框架找inSampleSize的方式
volley:会按照2的指数增长的方式去找
static int findBestSampleSize( int actualWidth, int actualHeight, int desiredWidth, int desiredHeight) { double wr = (double) actualWidth / desiredWidth; double hr = (double) actualHeight / desiredHeight; double ratio = Math.min(wr, hr); float n = 1.0f; while ((n * 2) <= ratio) { n *= 2; } return (int) n; }
Xutils
public static int calculateInSampleSize(BitmapFactory.Options options, int maxWidth, int maxHeight) { final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (width > maxWidth || height > maxHeight) { if (width > height) { inSampleSize = Math.round((float) height / (float) maxHeight); } else { inSampleSize = Math.round((float) width / (float) maxWidth); } final float totalPixels = width * height; final float maxTotalPixels = maxWidth * maxHeight * 2; while (totalPixels / (inSampleSize * inSampleSize) > maxTotalPixels) { inSampleSize++; } } return inSampleSize; }
uil_imageLoader:做的比较细.会按照不同的scaleType采用不同的算法,而且也是按照了2的指数增长的形式去操作
int scale; if (scaleType == ImageScaleType.NONE) { scale = 1; } else if (scaleType == ImageScaleType.NONE_SAFE) { 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()); } //隔开 public static int computeMinImageSampleSize(ImageSize srcSize) { final int srcWidth = srcSize.getWidth(); final int srcHeight = srcSize.getHeight(); final int targetWidth = maxBitmapSize.getWidth(); final int targetHeight = maxBitmapSize.getHeight(); final int widthScale = (int) Math.ceil((float) srcWidth / targetWidth); final int heightScale = (int) Math.ceil((float) srcHeight / targetHeight); return Math.max(widthScale, heightScale); // max } public static int computeImageSampleSize(ImageSize srcSize,ImageSize targetSize, ViewScaleType viewScaleType,boolean powerOf2Scale) { final int srcWidth = srcSize.getWidth(); final int srcHeight = srcSize.getHeight(); final int targetWidth = targetSize.getWidth(); final int targetHeight = targetSize.getHeight(); int scale = 1; switch (viewScaleType) { case FIT_INSIDE: if (powerOf2Scale) { final int halfWidth = srcWidth / 2; final int halfHeight = srcHeight / 2; while ((halfWidth / scale) > targetWidth || (halfHeight / scale) > targetHeight) { // || scale *= 2; } } else { scale = Math.max(srcWidth / targetWidth, srcHeight / targetHeight); // max } break; case CROP: if (powerOf2Scale) { final int halfWidth = srcWidth / 2; final int halfHeight = srcHeight / 2; while ((halfWidth / scale) > targetWidth && (halfHeight / scale) > targetHeight) { // && scale *= 2; } } else { scale = Math.min(srcWidth / targetWidth, srcHeight / targetHeight); // min } break; } if (scale < 1) { scale = 1; } scale = considerMaxTextureSize(srcWidth, srcHeight, scale, powerOf2Scale); return scale;
}
内存缓存:集合存对象
- 1.内存缓存的核心操作:
- 存:就有很多的考虑
- 取:唯一索引性
- 2.选择什么样的
存储结构/容器/集合
?map
LruCache的使用:
一个内存缓存工具类,提供了基于
Lru缓存策略
的强引用
的内存缓存,存储结构使用的LinkedHashmap
LruCache实现原理
LinkedHashmap使用
- LinkedHashmap和Hashmap区别:在构造方法里面多了3个参数
- 3个参数的意义:
- initialCapacity:初始化容器大小 16
- loadFactor:负载因子
- accessOrder:
- true:LinkedHash内部会排序–>按照访问顺序排序–>这个也是为什么LruCache使用LinkedHashmap做存储结构的原因
- false:按照插入顺序去排序
LruCache在什么地方可以找到?
- 在高版本的sdk里面有.
- 在v4包中有提供.
- LruCache的使用
- 告知缓存的具体大小
- 覆写sizeOf方法,
- 告知放入LruCache中具体实体的大小
- 和maxSize中定义的单位统一
磁盘缓存
可以使用android 2013 i/o大会提供的LruDiskCache
如何使用LruDiskCache
1.初始化好LruDiskCache
LruDiskCache mDiskLruCache = LruDiskCache.open(diskCacheDir, 1, 1, diskCacheSize);
2.取
LruDiskCache.Snapshot snapshot = mDiskLruCache.get(uri);
FileInputStream in = snapshot.getInputStream();
//in-->Bitmap
public static Bitmap decodeStream(InputStream is)
3.存
LruDiskCache.Editor editor = mDiskLruCache.edit(uri);
FileOutPutStream outputStream = editor.newOutputStream(DISK_CACHE_INDEX);
//bitmap-->outPutStream
public boolean compress(CompressFormat format, int quality, OutputStream stream)
网络请求的取消
httpclient:
DefaultHttpClient httpClient = new DefaultHttpClient(); ClientConnectionManager connectionManager = httpClient.getConnectionManager();// 拿到连接管理器 connectionManager.shutdown();
volley:多级别取消
- 取消某一个请求:
取消请求的队列:
//2. 创建RequestQueue RequestQueue queue = Volley.newRequestQueue(MainActivity.this); //3. 发起请求 queue.add(stringRequest); //取消单个请求 stringRequest.cancel();//取消一个请求 //取消所有请求 queue.cancelAll(null);//取消请求队列里面所有的方法 //取消置顶tag的请求 queue.cancelAll("tag1");//取消tag为tag1的一个请求 //请求添加tag-->tag的目的就是为了反查 stringRequest.setTag("tag1"); //两个不同的请求可以设置同一个tag stringRequest.setTag("tag1"); // stringRequest1.setTag("tag1");
- xutils:xutils其实也是封装的httpclient,所以网络请求取消的方式和httpClient一样
生命周期的联动
StringRequest req1 = null; StringRequest req2 = null; StringRequest req3 = null; StringRequest req4 = null; StringRequest req5 = null; req1.setTag(this.getClass().getSimpleName()); req2.setTag(this.getClass().getSimpleName()); req3.setTag(this.getClass().getSimpleName()); req4.setTag(this.getClass().getSimpleName()); req5.setTag(this.getClass().getSimpleName()); // 取消对应activity里面所有的请求 RequestQueue queue = VolleyTools.getInstance(MainActivity.this).getQueue(); queue.cancelAll(this.getClass().getSimpleName());// MainActivity
uil imageLoader
- 3个核心类
ImageLoaderConfiguration:imageloader的配置
简单的实例化方式
`ImageLoaderConfiguration config = ImageLoaderConfiguration.createDefault(getApplicationContext());`
自定义复杂的实例化方式
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(context) .threadPriority(Thread.NORM_PRIORITY - 2) .denyCacheImageMultipleSizesInMemory() .diskCacheFileNameGenerator(new Md5FileNameGenerator()) .diskCacheSize(50 * 1024 * 1024) // 50 Mb .tasksProcessingOrder(QueueProcessingType.LIFO) .writeDebugLogs() // Remove for release app .build();
- ImageLoader:图片加载器
DisplayImageOptions:显示效果
- 支持圆角效果
- 支持淡入淡出效果
步骤
1.在Application子类里面的oncreate(程序的入口方法)方法中,初始化好
ImageLoaderConfiguration
,可以使用默认的配置也可以使用自定义配置,uil imageloader提供了非常丰富的配置;2.使用ImageLoader.getInstance()去直接加载图片ImageLoader.getInstance().displayImage(uri, mIv);
3.可以通过DisplayImageOptions创建默认的展示效果.或者自定义展示效果
uil imageloader和其他框架的区别
0.github上starts以及forks
1.丰富的缓存策略,配置比较丰富 差不多30个配置
2.根据imageView的scalType进行计算缩放值 option.insamplesize
3.HTTP(“http”), HTTPS(“https”), FILE(“file”), CONTENT(“content”), ASSETS(“assets”),加载类型比较多
4.提供了丰富的缓存策略
内存缓存
现在我们来看Universal-Image-Loader有哪些内存缓存策略
1. 只使用的是强引用缓存
LruMemoryCache(这个类就是这个开源框架默认的内存缓存类,缓存的是bitmap的强引用,下面我会从源码上面分析这个类)
2.使用强引用和弱引用相结合的缓存有
UsingFreqLimitedMemoryCache(如果缓存的图片总量超过限定值,先删除使用频率最小的bitmap)
LRULimitedMemoryCache(这个也是使用的lru算法,和LruMemoryCache不同的是,他缓存的是bitmap的弱引用)
FIFOLimitedMemoryCache(先进先出的缓存策略,当超过设定值,先删除最先加入缓存的bitmap)
LargestLimitedMemoryCache(当超过缓存限定值,先删除最大的bitmap对象)
LimitedAgeMemoryCache(当 bitmap加入缓存中的时间超过我们设定的值,将其删除)
3.只使用弱引用缓存
WeakMemoryCache(这个类缓存bitmap的总大小没有限制,唯一不足的地方就是不稳定,缓存的图片容易被回收
硬盘缓存
FileCountLimitedDiscCache(可以设定缓存图片的个数,当超过设定值,删除掉最先加入到硬盘的文件)
LimitedAgeDiscCache(设定文件存活的最长时间,当超过这个值,就删除该文件)
TotalSizeLimitedDiscCache(设定缓存bitmap的最大值,当超过这个值,删除最先加入到硬盘的文件)
UnlimitedDiscCache(这个缓存类没有任何的限制)
5.使用简单
架构
b/s架构:绘图说明
mvc:设计思想
- M:model
- V:view
- C:Ctroller
mvp:设计思想
- M:model
- V:View
- P:Presenter
四层架构:自我总结
- 数据提供层–>dataProvider:提供数据
- 数据持久层–>data persistent–>sqlite ,sp,file
- 业务逻辑层–>servcie logic
- ui展现层
gzip
一种压缩格式,一种压缩方式,可以对
网络传输的数据
进行压缩.减少网络传输的大小
为什么需要压缩?
- 减少体积,提高传输速度,提高用户体验
浏览器发送器请求的过程?
- 1.发送请求头:
Accept-Encoding:gzip
- 2.服务器压缩数据,返回数据,在响应头里面添加
Content-Encoding:gzip
- 3.客户端,根据Content-Encoding这个响应头,对应解压
- 有Content-Encoding:gzip–>gzip解压
- 没有Content-Encoding:gzip–>标准解压
- 1.发送请求头:
- app使用gzip压缩
- 返回的json/xml(文本信息)其实就是个特殊的网页,其实也是可以进行gzip压缩
gzip压缩效果
通过数据,我们得知,文本的压缩率,大概可以达到70%左右.压缩率很高;
gzip压缩的实现
try {
boolean isGzip = false;
//1.创建httpclient
DefaultHttpClient httpClient = new DefaultHttpClient();
//2.创建get请求
HttpGet get = new HttpGet("http://httpbin.org/gzip");
//① 添加请求头 Accept-Encoding:"gzip, deflate"
get.addHeader("Accept-Encoding", "gzip");
//3.执行请求
HttpResponse response = httpClient.execute(get);
if (response.getStatusLine().getStatusCode() == 200) {
//② 得到响应头,Content-Encoding:"gzip"
Header[] headers = response.getHeaders("Content-Encoding");
for (Header header : headers) {
if (header.getValue().equals("gzip")) {//后台server把数据进行了gzip压缩
isGzip = true;
}
}
String result = "";
HttpEntity entity = response.getEntity();
//③根据是否使用gzip压缩.采取不同的解压方式
if (isGzip) {
//④进行gzip的解压
GZIPInputStream in = new GZIPInputStream(response.getEntity().getContent());
//in-->string
result = convertStreamToString(in);
} else {
//4.打印结果
result = EntityUtils.toString(entity);
}
System.out.println("result:" + result);
}
} catch (Exception e) {
e.printStackTrace();
}
测试请求的地址
http://httpbin.org
常见的content-type
- application/x-www-form-urlencoded:表单,key-value
- multipart/form-data:二进制,file
- application/json :json,虽然有的服务器直接用
text/plain
这个请求头没有任何问题.但是很多服务器,必须需要application/json
,明确的说.如果是返回json,一定加上application/json
,不要用默认的.实际开发遇到了几次这样的问题.或者说.加上这个请求头肯定是万无一失; - text/xml :xml
- text/plain:普通文本,默认类型
模拟请求插件restClient的使用
这个是firefox上的一个插件,对应chrome浏览器叫做postman,这个插件主要用作和服务器开发人员联调协议;
- key-value:
- 1.添加head–>Content-Type
- 2.传递参数:key=value&key=value
- jsonString
- 1.添加head
- 2.传递参数:jsonString