一:网络框架的优缺点
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/watch?v=yhv8l9F44qo&feature=player_embedded
简单的使用:http://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 文件
<attr name="TitleTexTColor" format="color"/>
<declare-styleable name="CustomTitleView">
<attr name="TitleText"/>
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 比较