android中的知识整理


progressBar
更新progressBar的进度时,  ,可以不在主线程中  progressBar.setProgress();
因为progressBar内置了判断 ,,如果不在主线程更新的话
会自动加入到主线程中更新   进度

获取系统服务
context.getSystemService()';

隐式意图   ::::
activity在manifest中的 intentfilter中配置 <data scheme="itcast"/>属性表示
在调用时用必须传递数据,为   intent.setData(Uri.parse("itcast:xxxx"));
category 其实就是用来指定  额外的 附加信息

如果在 manifest 文件中配置 ,activity 时,添加的主题为 dialog的话,activity就以对话框显示
如,,,android:theme="@android:style/Theme.Dialog"

创建对话框  
1 首先拿到对话框的构造器、
AlertDialogBuilder builder = new Builder(this);
builder.setTitle("提醒");
builder.setMessage("这是一个对话框里的主体内容");
builder.setPositiveButton("确定",OnclickListener);
2 最后别忘了
builder.create().show();

任务栈 :::
任务栈 只针对    activity     而言

activity 启动模式   
singletop启动模式 的主要功能是避免同一个界面被重复开启
singletask启动模式 主要是避免创建过多的activity实例
像浏览器这种笨重的activity,
可以节约内存空间  cpu资源
singleinstance启动模式 整个操作系统只有一个实例存在
例如手机接收来电activity,有道词典快速取词


令activity横竖屏转换时不被销毁创建可以在activity中配置如下属性
android:configChanges="orientation|keyboardHidden|screensSize";


service ::::::::
做耗时操作+  提供服务给其他应用进行通信2016/7/31
bindService跟生命周期绑定在一起


补间动画的缺点::::
没有更改view的属性(x,y);而是重新绘制出来的
所以说才有  属性动画   出场


应用程序:::::
其实就是   一组组件(activity,,service,,provider,,receiver)的 集合
一般情况下,,一个应用程序对应一个进程
一般情况下,,关闭应用(关闭掉所有的界面,关闭所有activity)


采用一组策略 帮助我们自动的管理进程
进程按照优先级分为 5个 不同的等级
1.前台进程
2.可见进程
3.服务进程,,如果是自动服务进程杀死了,,当内存有充足时
会快速把杀死的服务进程  有复活回来
4.后台进程
5.空进程
为什么要在服务中运行呢, 而不是在activity中new线程运行呢??
因为生命周期不一样
因为如果用户把activity中推出的话,,该应用很容易变成 空进程
容易被销毁,,而服务属于高优先级,,
适合才后台长期运行


服务是不能直接new出来    new出来的服务只能是普通的对象
服务的对象  是被系统(框架)new 出来的
bindservice绑定服务 可以间接地得到服务的代理人对象IBinder
serviceConnection里的抽象方法 onserviceDisconnected方法
只有才服务失去绑定的时候调用,如程序异常终止
服务的代理人对象也是不能那么容易拿到的,根据java封装对象的思想
IBinder的实现类应该 为 private 的,,把IBinder实现类里的可以对外暴露的方法
抽象成接口IService,,然后再onbind方法里返回IBinder实现类
外部通过强制类型转换成 ISerivce接口,然后掉用该接口里的方法
IBinder实现类是不能直接访问


绑定服务::可以间接调用服务里的方法
如果调用者activity被销毁了,服务也会跟着销毁
所以需要在activity 销毁时,,
调用unbindService方法解绑服务,不然报异常
开启服务::不可以调用服务里的方法 
如果调用者activity退出了,,服务还会长期地在后台运行 、


注意::::如果既要保证服务长期在后台运行,又想调用服务里的方法。
步骤:::::1.先开启服务 startService()---onCreate();
2.绑定服务 bindService()--onbind(); 这样就可以了
3.关闭程序,调用者退出,,服务被解绑
4.stopService();  停止服务
需按照上述步骤来,,如果先绑定了服务的话,服务也会开启
但是stopService();方法就会失效,,必须先解绑服务才可以
且服务  只能被解绑一次,否则报异常
技巧:如果不能保证activity退出时是否已经解绑了,
可以在onDestory方法里把unbindservice方法try/catch下


IPC:::(inter process communication) 内部进程间通讯


四大组件   的特点    就是要在清单文件中配置
但是但是但是::广播接收者broadcast receiver可以通过清单文件配置
也可以通过   代码    的方式配置两种。特殊
this.registerReceiver(receiver,filter);


MediaPlayer 的不足::::
1.资源占用量较高,,,
2.延迟时间长,    
3.不支持多个音频是同播放
在对时间精度要求相对较高的游戏开发中,,
多使用 SoundPool。。。
池:::实质上就是一个    链表   的结构


播放视频  使用   SurfaceView
其   内部维护了    双缓冲      技术
就是两个线程  快速地做   前后台切换---解析帧---显示到界面
如果发现当前SurfaceView  用户可见的时候,创建surfaceview的Holder
如果surfaceview 变成用户不可见的时间  销毁surfaceview的  holder




进度条 还有进度条对话框   这些比较特殊的控件 ,,,,可以在子线程 修改
原因是 其内部    封装了如果不是在   ui线程,修改的话
会自动加入   ui线程  修改


parcelable 是两个进程间的通讯类型


fragment::::???????????
就是 相当于  view+生命周期,,并且依附在activity中


getApplicationContext和activity。this的区别?????
getApplicationContext();的生命周期长,只要用应用存在,,它就存在
activity.this生命周期短。只要activity不存在;了,需用就会回收
其中只有activity.this才能用在alertdialog

推荐用法,:::activity.this
getApplicationContext的使用场景是比如频繁需要操作的数据库


如果 listview 的adapter 不能 给被 充气 的view 添加父控件 否则 wid,hei,
会改为wrap
LayoutInflater.from(context).inflate(R.layout.view_setting_item,parent,false);
上述方法返回view有两个可能,根据parent是否为空,空返回的view为R.layout.view_setting_item
非空,返回的 view  就是listview本身。
第三个参数,觉得返回值,ture 返回listview,false,返回R文件
如果inflate带父 控件,而且第三个参数为false,则子控件的 attr属性转换为 LayoutParams添加到父空间
而不用 addview的方式添加 到 listview  ,,因为 adapterview的子类是不可以以addview的方式添加子控件
最直接的结果就是,,子控件 的 wid,hei,属性可以自己定义长度,且有效
但是如果第三个参数为 true ,则 子控件的 wid,hei,无论写了什么,都为wrap
因为 子控件的 attr属性 并没有 转换 为 LayoutParams添加到 parent中

----查找的过程
* 1 导入Setting的源码到eclipse里面
* 2 “缓存”在手电筒(file search)--->String.xml--->"cache_size_label"
* 3 "cache_size_label"在手电筒(file search)--->installed_app_details.xml--->cache_size_text
* 4 "cache_size_text"在手电筒(file search)---->InstalledAppDetails.java--->mCacheSize(TextView)
* 5  "mCacheSize" ctrl+f --->mCacheSize.setText(getSizeStr(mAppEntry.cacheSize));---->mAppEntry.cacheSize
* 6  "mCacheSize" ctrl+shit+g---> 找到谁调用它ApplicationsState.java---->entry.cacheSize = stats.cacheSize---->IPackageStatsObserver.Stub mStatsObserver = new IPackageStatsObserver.Stub()  (找远程接口 AIDL)
* 7 mStatsObserver ctrl+f---> 谁调用它--->   mPm.getPackageSizeInfo(mCurComputingSizePkg, mStatsObserver)---->PackageManager
* 8 点进去看PackageManager 的源码--->ctrl+o 找不到这个方法---->ctrl+f 就找到(@hide)


线程池的 优缺点:::
优点:线程池解决的 频繁的子线程和主线程的切换,主线程执行ui操作
子线程线程放耗时操作,避免卡顿,
因为线程还是比较重量级的,频繁new出来,会造成资源的浪费
缺点(围绕线程池):1.线程池不能存放太多的队列,,不然会爆掉
2.在旧版4.3中,同时执行max线程128,会造成频繁切换,浪费性能
,所以在4.4中改为了根据cpu的数量来决定max线程数
3.如果优先级不同的任务共享一个线程池,可能会造成低优先级任务
等待过长时间,特别是有网络操作
解决方法::使用executeOnExecutor()方法执行任务


首选字体大小sp  :::
谷歌官方推荐我们使用  12sp,,14sp,,18sp,,22sp,,
不推荐使用奇数的计量单位,,因为会造成精度的丢失


fragmentPagerAdatper::fragmentStatePagerAdapter
fragmentStatePagerAdapter是在tab项非常多的时候使用,用法类似listadapter


context
上下文是提供环境的,告诉程序一些信息  
以sqliteopenhelper为例
它的上下文就是告诉程序,数据库创建在哪一个目录下 
默认目录是 包名/ databases 下 创建数据库




context  和  activity 的区别
可以用activity的地方   ,不一定可以用context   .  例如  alertdialog、

可以用context的时候,,,虽然可以用activity  ,但是有时候并不适合
写公共方法时 ,,,尽量用context


进度条 还有进度条对话框   这些比较特殊的控件 ,,,,可以在子线程 修改
原因是 其内部    封装了如果不是在   ui线程,修改的话
会自动加入   ui线程  修改


os:::::operating systom


textView.getHight();
TextView.getWidth();
这两个方法需要在界面显示之后才会有值,,,
在没有显示之前,,得到的数值为0;
如果想要在没有显示之前获取 width, height,的话,,就要先测量
就是 textView.measure(0,0); 
然后  textView.getmeasuredwidth();
textView.getmeasuredHeight();


什么是 延迟始化::;lazy initilization
就是一开始的时候不new 出来,,
等待用的时候,如果还没new  就 new 出实例来,并且保存带集合中
一般这个集合都是 < ? exntends Map>集合 键值对的形式
另外 如果使用的key 是 integer 类型,则建议用sparseArray集合
下次再用的话,,就不会直接new 出来 ,,而是从集合中取出来


堆 和  栈:::::
局部变量的基本数据类型和引用存储于栈中,引用的对象实体存储于堆中。
—— 因为它们属于方法中的变量,生命周期随方法而结束。


成员变量全部存储与堆中(包括基本数据类型,引用和引用的对象实体)
—— 因为它们属于类,类对象终究是要被new出来使用的。
2016/9/17


public class AppManager {
private static AppManager instance;
private Context context;
private AppManager(Context context) {
this.context = context;
}
public static AppManager getInstance(Context context) {
if (instance == null) {
instance = new AppManager(context);
}
return instance;
}}
————单例造成的内存泄漏————
可以看到,上面的单例的对象需要传入一个context,
如果传入的context为 application的context,则没有任何问题
如果,传入的context 为 activity 的context,
那么该activity 将无法销毁,一直被单例对象持有者,
activity无法销毁是 非常严重的 内存泄漏
——这个时候就有两种修改代码的办法,
1.。
this.context = context; 改为 this.context = context.getApplicationContext();
2...  在application 对象中声明一个静态的applicationContext,然后调用
这样的话连context都不用传进来了
this.context = MyApplication.getContext();// 使用Application 的context


内存泄漏::
在java中,非静态内部类(包括匿名内部类)会引用外部类对象(比如activity)
而静态内部类 则不会 引用外类对象
那么问题来了,
如果在activity 声明非静态handler 匿名类对象 ,,如果activity销毁了
而这个handler任然引用者activity对象就会导致内存泄漏
因为handler会在一段时间内被 mainLooper持有者,导致引用仍然存在

activity中应该避免使用非静态内部类的 静态实例,,
因为该实例生命周期于应用一样长并且持有activity的引用就内存泄漏


如果在activty/fragment/view中,使用了匿名类,被异步线程持有了,就
会导致内存泄漏
Handler为匿名内部类,如果hanlder的message尚未被处理,那么该message
以及发送他的handler对象就会被Messagequeue(MainLooper)一直持有
从而导致 内存泄漏。。这是因为handler 属于TLS(Thread Local Storage)
变量,生命周期和activity不一致,故很容易导致无法正确释放
解决办法:: 因为这个内存泄漏最为常见
在activity中避免使用非静态内部类,而使用静态的handler类+
weakReference的方式,每次使用引用前要判断非空
非空判断是因为,弱引用的activity,在系统发生gc会清空
即:WeakReference<MyActivity> mActivity = new WeakReference<MyActivity>(activity);
使用时: MyActivity activity = mActivity.get();
不过虽然必秒的activity的泄漏,但是Looper还是可能会有等待处理的消息
所有我们要在activity的ondestory或者onstop方法应移除消息
handler.removeAllCallbacks 或者 handler.removeCallbacksAndMessages
Bitmap::
没有调用recycle()方法,对于bitmap对象在不使用的时候应该先recycle然后
再把bitmap置为null,因为加载bitmap对象的内存空间,一部分是java的
一部分是 c(因为 Bitmap 分配的底层是通过 JNI 调用的)  的 
,recycle()就是针对C部分的内存释放。
内存泄漏总结:::
对 Activity 等组件的引用应该控制在 Activity 的生命周期之内;
如果不能就考虑使用 getApplicationContext 或者 getApplication,
以避免 Activity 被外部长生命周期的对象引用而泄露。
尽量不要在静态变量或者静态内部类中使用非静态外部成员变量(包括context ),即使要使用,
也要考虑适时把外部成员变量置空;也可以在内部类中使用弱引用来引用外部类的变量。
对于生命周期比Activity长的内部类对象,并且内部类中使用了外部类的成员变量,可以这样做避免内存泄漏:
将内部类改为静态内部类, 静态内部类中使用弱引用来引用外部类的成员变量


模板设计模式的含义::
你修改了子类,,影响了父类的结果,这就是模板设计模式


StateListDrawable:::::::::
设置stateListDrwable的addstate方法的时候,,new Inte[]{} 多参数的数组一定要放在前面,否则很可能不起作用


nineOldAndroid框架::::
这个框架是用来兼容低版本的 属性动画的,,因为属性动画是android3.0才出现的













  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值