Android网络框架的优缺点、图片加载框架等基础知识讲解
一:网络框架的优缺点
1.volley
优点:
(1)自动调度网络请求;
(2)高并发网络连接;
(3)通过标准的 http cache coherence(高速缓存一致性)缓存磁盘和内存透明的响应;
(4)支持指定请求的优先级( 请求队列的优先级排序);
(5) 提供多样的取消机制:网络请求 cancel 机制,我们可以取消单个请求,或者指定取消请求队列中的一个区域;
(6)框架容易被定制,例如,定制重试或者回退功能;
(7)包含了调试与追踪工具;
(8)默认 android2.3 及以上基于 httpurlconnection,2.3 以下使用基于 httpclient
(9)提供简便的图片加载工具(其实图片的加载才是我们最为看重的功能)
缺点:
(1)不能下载文件:这也是它最致命的地方
官网或相关地址:
volley 的 github 地址:https://github.com/mcxiaoke/android-volley;
google i/o 2013 – volley: easy, fast networking for android:https://www.youtube.com/watchv=yhv8l9f44qo&feature=player_embedded
简单的使用:https://www.dengzhr.com/others/mobile/android/762
2.okhttp
3.retrofit
(1)支持 okhttp
(2)注解处理,简化代码
(3)支持上传和下载文件
(4)支持自己更换解析方式
(5)支持多种http请求库
二:图片加载框架
1.picasso :和square的网络库一起能发挥最大作用,因为picasso可以选择将网络请求的缓存部分交给了okhttp实现。
1.glide :模仿了picasso的api,而且在他的基础上加了很多的扩展(比如gif等支持),glide默认的bitmap格式是rgb_565,比
picasso默认的argb_8888格式的内存开销要小一半;picasso缓存的是全尺寸的(只缓存一种),而glide缓存的是跟
imageview尺寸相同的(即56*56和128*128是两个缓存) 。
3.总结:picasso所能实现的功能,glide都能做,无非是所需的设置不同。但是picasso体积比起glide小太多如果项目中网络请求本身用的
就是okhttp或者retrofit(本质还是okhttp),那么建议用picasso,体积会小很多(square全家桶的干活)。glide的好处是大型的图片流,
比如gif、video,如果你们是做美拍、爱拍这种视频类应用,建议使用。
三:activity
启动模式:
1.standard:默认模式,可以不用写配置。在这个模式下,都会默认创建一个新的实例。因此,在这种模式下,可以有多个相
同的实例,也允许多个相同activity叠加。
2.singletop:可以有多个实例,但是不允许多个相同activity叠加。即,如果activity在栈顶的时候,启动相同的activity,
不会创建新的实例,而会调用其onnewintent方法。
3.singletask:只有一个实例。在同一个应用程序中启动他的时候,若activity不存在,则会在当前task创建一个新的实例,
若存在,则会把task中在其之上的其它activity destory掉并调用它的onnewintent方法。
4.singleinstance:只有一个实例,并且这个实例独立运行在一个task中,这个task只有这个实例,不允许有别的activity存在。
生命周期:
1.oncreate:create表示创建,这个界面创建的时候就会执行此方法
2.onstart:启动这个界面,这个界面开始可见
3.onresume:这个界面可以交互,你可以点击,滑动等
4.onpause:这个界面可见,但是不可交互,
场景:activity 上面有一个对话框之类的,下面的界面可以见,但是无法交互
5.onstop:关闭这个界面,但是这个界面还是存在的,只是看不见
场景:按住home键,返回出去,但是这个活动还在,但是看不见了
6.ondestroy:将这个activity销毁,不可见,不可交互,可以做一些资源释放
7.onrestart:重新启动这个界面 执行 onstart onresume 不执行 oncreate方法
横竖屏切换:
1.不设置activity的android:configchanges时,切屏会重新调用各个生命周期,切横屏时会执行一次,切竖屏时会执行两次
2.设置activity的android:configchanges="orientation"时,切屏还是会重新调用各个生命周期,切横、竖屏时只会执行一次
3.设置activity的android:configchanges="orientation|keyboardhidden"时,切屏不会重新调用各个生命周期,
只会执行onconfigurationchanged方法
android:screenorientation="portrait"
则无论手机如何变动,拥有这个属性的activity都将是竖屏显示。
android:screenorientation="landscape",为横屏显示
两个界面跳转:
打开app时
mainactivitya:oncreate —>在activitya对象被第一次创建时
mainactivitya:onstart —>activitya变得可见
mainactivitya:onresume —>开始准备与用户交互时调用
此时点击activitya中的按钮时:
mainactivitya:onpause —>即将启动另外一个activitb之前
otheractivityb:oncreate —>在activityb对象被第一次创建时
otheractivityb:onstart —>activityb变得可见
otheractivityb:onresume —>开始准备与用户交互时调用
mainactivitya:onstop —>当前activitya变得不可见时
点击activityb中的 返回 按钮时 :
otheractivityb:onpause —>即将启动另外一个activitb之前
mainactivitya:onrestart —>activitya再次启动之前
mainactivitya:onstart —>activitya变得可见
mainactivitya:onresume —>开始准备与用户交互时调用
otheractivityb:onstop —>当前activityb变得不可见时
otheractivityb:ondestroy —>当前activityb被销毁之前
mainactivitya:onstop —>当前activityb变得不可见时
mainactivitya:ondestroy —>当前activityb被销毁之前
四:handler机制、原理:
为什么要有handler:如果多线程并发的话就会造成界面混乱,不可控的状态。
handler , looper, massage,massagequeue
1.messagequeue:消息队列。虽然名为队列,但事实上它的内部存储结构并不是真正的队列,而是采用单链表
的数据结构来存储消息列表的,其中主要有插入enqueue()和从中拿走并删除next()两个方法。
2.looper:消息循环。messagequeue 来存储消息,looper 则是以无限循环的方式去查找是否有新消息,
如有就去处理,若没有就standby(等待).
注 : 一个线程创建handler时首先需要创建 looper 的,不然报错:但是ui线程是不需要创建的,
是因为 activitytread 创建时就初始化了 looper
3.handler:通过 sendmessage 或者 post 去将消息发送到messagequeue中,会调用 enqueuemessage() 方法,
而 messagequeue 的 next() 方法会将该消息返回给looper,looper接收到消息,就会处理
--looper 就交由 handler 的 dispatchmessage 方法
4.handler 的 dispatchmessage 方法最终会调用handlermessage 方法来处理消息:
五:自定义view:
1.自定义属性: values/新建一个 attrs.xml 文件
2.获取自定义属性:typedarray a = context.gettheme().obtainstyledattributes(attrs, r.styleable.customtitleview, defstyle, 0);
int n = a.getindexcount();
for (int i = 0; i < n; i++)
{
int attr = a.getindex(i);
switch (attr)
{
case r.styleable.customtitleview_titletext:
mtitletext = a.getstring(attr);
break;
case r.styleable.customtitleview_titletextcolor:
// 默认颜色设置为黑色
mtitletextcolor = a.getcolor(attr, color.black);
break;
case r.styleable.customtitleview_titletextsize:
// 默认设置为16sp,typevalue也可以把sp转化为px
mtitletextsize = a.getdimensionpixelsize(attr, (int) typedvalue.applydimension(
typedvalue.complex_unit_sp, 16, getresources().getdisplaymetrics()));
break;
}
}
a.recycle();
3.重写 onmesure:
4、重写ondraw :
//画背景
mpaint.setcolor(color.yellow);
canvas.drawrect(0, 0, getmeasuredwidth(), getmeasuredheight(), mpaint);
//画自己设置的内容
mpaint.setcolor(mtitletextcolor);
canvas.drawtext(mtitletext, getwidth() / 2 - mbound.width() / 2, getheight() / 2 + mbound.height() / 2, mpaint);
六::https://www.cnblogs.com/picaso/archive/2012/05/17/2505895.html
七:fragment:android 3.0 引入
//创建了一个fragment 代表一个页面
public class test1fragment extends fragment {
//通过下面这个方法加载布局
@override
public view oncreateview(layoutinflater inflater, viewgroup container, bundle savedinstancestate) {
//加载布局 通过打气筒加载
return inflater.inflate(r.layout.fragment_test1, null);
}
}
1.获取 手机宽高:
//1.获取手机宽高
windowmanager wm = (windowmanager) getsystemservice(window_service);
int width = wm.getdefaultdisplay().getwidth();
int height = wm.getdefaultdisplay().getheight();
//2.获取一个fragment的管理者
fragmentmanager fragmentmanager = getfragmentmanager();
//2.1 开启fragment事务
fragmenttransaction fragmenttransaction = fragmentmanager.begintransaction();
//3.判断手机状态是横屏还是竖屏
if (height > width){
//说明是竖屏 加载一个页面 参数1:android.代表定义好的一些id 理解成是当前手机窗口
fragmenttransaction.replace(android.r.id.content,new test1fragment());
}else{
//说明是横屏 加载另外一个页面
fragmenttransaction.replace(android.r.id.content,new test2fragment());
}
//4.最后一步 记得提交事务
fragmenttransaction.commit();
八:listview与scrollview滑动冲突
4.最优方法,重写onmeasure方法 改变他回获取高度的方式
@override
protected void onmeasure(int widthmeasurespec, int heightmeasurespec) {
int expandspec = measurespec.makemeasurespec(integer.max_value >> 2,
measurespec.at_most);
super.onmeasure(widthmeasurespec, expandspec);
}
//其他方法:
1.在布局里面将listview的高度 固定,简单粗暴,适合新手
2.使用单个listview的addheaderview()方法添加一个头条目,检测状态,如果你需要检测头部状态的话,还是有冲突
3.使用linearlayout取代listview 用循环将数据添加进去。
九:listview的优化:
优化1:convertview的使用,主要优化加载布局问题
优化2:内部类viewholder的使用。减少findviewbyid()的次数;
优化3:static viewholder 类,只加载一次
额外优化:
1.有网络图片时:
如果你的listview中需要显示从网络上下载的图片的话,我们不要在listview滑动的时候加载图片,那样会使listview变得卡顿,
所以我们需要再监听器里面监听listview的状态,如果滑动的时候,停止加载图片,如果没有滑动,则开始加载图片
listview.setonscrolllistener(new onscrolllistener() {
@override
public void onscrollstatechanged(abslistview listview, int scrollstate) {
//停止加载图片
if (scrollstate == abslistview.onscrolllistener.scroll_state_fling) {
imageloader.stopprocessingqueue();
} else {
//开始加载图片
imageloader.startprocessingqueue();
}
}
@override
public void onscroll(abslistview view, int firstvisibleitem, int visibleitemcount, int totalitemcount) {
// todo auto-ge nerated method stub
}
});
2 scrollingcache: scrollingcache本质上是drawing cache,你可以让一个view将他自己的drawing保存在cache中
(保存为一个bitmap),这样下次再显示view的时候就不用重画了,而是从cache中取出。默认情况下drawing cahce是禁用的,
因为它太耗内存了,但是它确实比重画来的更加平滑。而在listview中,scrollingcache是默认开启的,我们可以手动将它关闭。
3.animatecache: listview默认开启了animatecache,这会消耗大量的内存,因此会频繁调用gc,我们可以手动将它关闭掉
4.减少item的布局的深度;
十:a 应用启动 b 应用:
intent intent = getpackagemanager().getlaunchintentforpackage("com.xiecc.seeweather");
if (intent != null) {
intent.putextra("type", "110");
intent.setflags(intent.flag_activity_new_task);
startactivity(intent);
}
注:在次之前需要判断 b 应用是否存在
十一:网络七层协议
应用层 --> telnet,http,ftp,nfs,smtp 等。
表示层 --> ,ascii 等
会话层 --> rpc,sql 等。
传输层 --> tcp,udp,spx。这层对端到端的包传输进行定义,它定义了能够标识所有结点的逻辑地址,
网络层 --> ip,ipx 等。 它定义了在单个链路上如何传输数据
数据链路层 -->atm,fddi 等。
物理层 --> rj45,802.3等。
计算机组成:计算机组成指的是系统结构的逻辑实现,包括机器机内的数据流和控制流的组成及逻辑设计等。
主要分为五个部分:控制器,运算器,存储器,输入设备,输出设备。
十二:定位的坑
1.必须使用正式签名的apk。
2.必须使用真实手机测试,模拟机获取不到位置。
3.必须动态申请权限。(6.0以后)
error:execution failed for task ':app:transformclasseswithdexfordebug'.
> com.android.build.api.transform.transformexception: com.android.ide.common.process.processexception:
java.util.concurrent.executionexception: com.android.dex.dexexceptionle: multiple dex fis define landroid/support/v4/app/navutils$navutilsimpl;
注:以上错误是v4包重复,v7包 包含 v4包
十三:a 应用拉起 b 应用
1. 获取所有的包名
intent intent = new intent(intent.action_main, null);
intent.addcategory(intent.category_launcher);
apps = getpackagemanager().queryintentactivities(intent, 0);
2. 通过包名拉起响应的app
intent intent = mainactivity.this.getpackagemanager().getlaunchintentforpackage("com.xiecc.seeweather");
startactivity(intent);
十四:事件分发:
十五:支付宝支付流程
十六:wifi列表是空的: 必须打开 gps ;
十七:手机完全独立:im号,获取 ,存在问题 6.0, 无法获取,wifi地址 也被屏蔽,返回 0.0.0.0;手机当中有取出厂商编号,拼成字符串。
网络框架问得多。基础(okhttp,httpurlconnection) volley 与 retrofit 比较