android版本号不能是float,Android知识点笔记

dispatchMessage() 分发消息三种情况

Message对象的callback不为空(runnable),交给callback处理

handler的callback不为空,交给callback处理(如果你消息自己有callback的话,就会优先执行你的消息的callback)

前两种都没有的情况下交给handleMessag去处理

Message的Obtain()/recycleUnchecked()

e6fb8e2965d3

e6fb8e2965d3

DialogFragment至少重写下面一个方法

onCreateView:自己通过XML定义布局

onCreateDialog:使用系统内置对话框比如AlertDialog

自定义View构造函数参数

一个参数:一般在直接New一个View的时候调用

两个参数:一般在layout文件中使用的时候会调用,关于它的所有属性(AttributeSet)(包括自定义属性,直接引用的Style资源)都会包含在attrs中传递进来

三个参数:默认的Style是指它在当前Application或Activity所用的Theme中的默认Style,且只有在明确调用的时候才会生效(AttributeSet未找到则从这里找)

四个参数:API21的时候才添加上,当第三个参数不生效时才有作用

优先级从高到低依次是:直接在layout中设置View的XML属性值(AttributeSet)> 设置View的style属性 > defStyleAttr > defStyleRes

Android安全机制分为三层

最基础的一层,数据分为system和data两个区。其中system是只读的,data用来存放应用自己的数据,这保证了系统数据不会被随意改写

第二层用来使应用之间的数据相互独立。每个应用都会有一个user id和group id,只有相同的user id才能问它们的数据。通过对apk签名来标识自己。签名和uid构成了双重的保证

第三个层次就是权限体系

调用的系统API接口,有3种目录可以给我们写入文件

应用私有存储(内置存储)不需要申请

Context.getFileDir():/data/data/应用包名/files/ 对应着App下清除数据

Context.getCacheDir():/data/data/应用包名/cache/ 对应着清除缓存

应用扩展存储(SD卡)API < 19:需要&API >= 19:不需要

Context.getExternalFilesDir():SDCard/Android/data/应用包名/files/

Context.getExternalCacheDir():SDCard/Android/data/应用包名/cache/

公共存储(SD卡)需要申请

Environment.getExternalStorageDirectory():SDCard/文件夹名字/

Bitmap 在内存当中占用的大小其实取决于

色彩格式,eg:如果是 ARGB8888 是像素4个字节,如果是 RGB565 是2个字节

原始文件存放的资源目录(是 hdpi 还是 xxhdpi 可不能傻傻分不清楚哈)

目标屏幕的密度(所以同等条件下,红米在资源方面消耗的内存肯定是要小于三星S6的)

解决屏幕旋转(状态发生变化)状态不能保持的问题

不好的实践:保存整个Activity使用设置android:configChanges属性,不止是屏幕旋转。比如修改设备默认语言,修改设备默认字体比例等都可会引起配置改变

已经被弃用的方法(API 13):重写onRetainNonConfigurationInstance()、getLastNonConfigurationInstance()方法

使用onSaveInstanceState() 、onRestoreInstanceState()进行数据保存与恢复

推荐的方法:在Retained Fragment中管理对象

扩展Fragment类,并声明对有状态对象的引用(onAttach引用Activity)

创建Fragment时调用setRetainInstance(boolean)

将片段添加到Activity

当Activity重新启动时,使用FragmentManager检索片段

FragmentTransaction中对Fragment的操作

add() & remove(): add()会执行onAttach()~onResume()周期,remove() 执行onPause()~onDetach()周期

show() & hide():生命周期方法不会执行,仅仅是View显示或者​隐藏,并视情况调用onHiddenChanged()

attach() & detach ():onPause()、onDestroyView()会被执行,Fragment的View也会被detach,但不会执行onDestroy()、onDetach()

replace():其实就是remove()+add()

TouchEvent事件,低8位表示touch事件的具体动作,比如按下,抬起,滑动,还有多点触控时的按下,抬起,这个和单点是区分开的

getAction:触摸动作的原始32位信息,包括事件的动作,触控点信息

getActionMask:触摸的动作,按下,抬起,滑动,多点按下,多点抬起

getActionIndex:触控点信息

TypedArray中的函数是获取自定义属性的,Resources中的函数是获取android预置属性的

getDimension()是基于当前DisplayMetrics进行转换,获取指定资源id对应的尺寸。函数的返回值是float,像素肯定是int

getDimensionPixelSize()与getDimension()功能类似,不同的是将结果转换为int,并且小数部分四舍五入

getDimensionPixelOffset()功能类似,不同的是将结果转换为int,并且偏移转换(offset)是直接截断小数位,即取整(其实就是把float强制转化为int)

系统属性SystemProperty

通过命令adb shell getprop查看手机上所有属性状态值

属性名称以“ro.”开头,那么这个属性被视为只读属性。一旦设置,属性值不能改变

属性名称以“persist.”开头,当设置这个属性时,其值也将写入/data/property

属性名称以“net.”开头,当设置这个属性时,“net.change”属性将会自动设置,以加入到最后修改的属性名

save&saveLayer

save方法可以保存当前的matrix and clip,并且在restore把它恢复,一些平移,旋转,缩放等操作都会影响Canvas的matrix,所以save操作一般可以保存这些信息以及clip信息

saveLayer则强大很多,它相当于另外起一张干净图层,并在上面进行绘制操作,然后在restoreToCount的时候,把刚才所绘制的重新绘制在原本的Canvas上。当时正如所知的那样,它会绘制两次,所以消耗是十分巨大

代码中获取attr属性的值

在xml里,我们可以简单的引用attr属性值,例如:

android:background="?attr/colorPrimary"

android:minHeight="?attr/actionBarSize"

代码中获取attr属性值:

TypedValue typedValue = new TypedValue();

context.getTheme().resolveAttribute(R.attr.yourAttr, typedValue, true);

// For string

typedValue.string

typedValue.coerceToString()

// For other data

typedValue.resourceId

typedValue.data;

Activity启动过程

e6fb8e2965d3

Activity启动过程

SparseArray

SparseArray 在某些条件下性能更好,主要是因为它避免了对key的自动装箱,内部是通过两个数组来进行数据存储的,一个存储key,另外一个存储value,但是由于其添加、查找、删除数据都需要先进行一次二分查找,所以在数据量大的情况下性能并不明显,将降低至少50%。

数据量不大,最好在千级以内

key必须为int类型,这中情况下的HashMap可以用SparseArray代替:

ArrayMap

ArrayMap是一个映射的,它设计上更多的是考虑内存的优化,内部是使用两个数组进行数据存储,一个数组记录key的hash值,另外一个数组记录Value值,它和SparseArray一样,也会对key使用二分法进行从小到大排序,在添加、删除、查找数据的时候都是先使用二分查找法得到相应的index,然后通过index来进行添加、查找、删除等操作,所以,应用场景和SparseArray的一样,如果在数据量比较大的情况下,那么它的性能将退化至少50%。

如果key的类型已经确定为int类型,那么使用SparseArray,因为它避免了自动装箱的过程,如果key为long类型,它还提供了一个LongSparseArray来确保key为long类型时的使用

如果key类型为其它的类型(String),则使用ArrayMap

两个数据结构都适合数据量不是特别大的情况

编译时候加上(据说编译比较快)

android{

...

tasks.whenTaskAdded { task ->

if (task.name.contains("lint")

//如果instant run不生效,把clean这行干掉

||task.name.equals("clean")

//如果项目中有用到aidl则不可以舍弃这个任务

||task.name.contains("Aidl")

//用不到测试的时候就可以先关闭

||task.name.contains("mockableAndroidJar")

||task.name.contains("UnitTest")

||task.name.contains("AndroidTest")

//用不到NDK和JNI的也关闭掉

|| task.name.contains("Ndk")

|| task.name.contains("Jni")

) {

task.enabled = false

}

}

}

ExecutorService的关闭方法

shutdown():将线程池状态置为SHUTDOWN,并不会立即停止

shutdownNow():将线程池状态置为STOP,企图立即停止,事实不一定

awaitTermination(): 当前线程阻塞,直到等所有已提交的任务(包括正在跑的和队列中等待的)执行完

Service

启动服务的需要通过 stopSelf() 自行停止,或其他组件调用 stopService()

onRebind()方法调用时机:

onUnbind()方法返回值为true

启动服务同时和绑定服务,当Activity退出的时候,Service的onUnbind()方法就会被调用

内容提供着权限有:

统一读写提供程序级别权限

单独的读取和写入提供程序级别权限

路径级别权限

临时权限

Android 6.0 Marshmallow的运行时权限

检查系统版本号:对于6.0开始的版本,才需要做运行时的权限检查

检查申请的权限:checkSelfPermission(Manifest.permission.xxx)

解释申请的权限:shouldShowRequestPermissionRationale()

执行申请权限操作:requestPermissions()

处理权限申请的结果:onRequestPermissionsResult()

Android安全机制

进程沙箱隔离机制

应用程序签名机制

权限声明机制

访问控制机制

进程通信机制

android中延迟执行某个任务

倒计时类

用CountDownTimer

延迟类

CountDownTimer,可巧妙的将countDownInterval设成和millisInFuture一样,这样就只会调用一次onTick和一次onFinish

handler.sendMessageDelayed,可参考CountDownTimer的内部实现,简化一下,个人比较推荐这个

TimerTask,代码写起来比较乱

Thread.sleep,感觉这种不太好

定时类

参照延迟类的,自己计算好要延迟多少时间

handler.sendMessageAtTime

AlarmManager,适用于定时比较长远的时间,例如闹铃

setBackgroundXXX的用法

setBackgroundDrawable 的参数为Drawable对象

setBackgroundColor 的参数为Color对象,比如说Color.Red为红色,或Color.rgb(255,0,0)

setBackgroundResource 的参数为资源ID,比如说R.drawable.icon

getDimension,getDimensionPixelOffset和getDimensionPixelSize

getDimension和getDimensionPixelOffset的功能类似,都是获取某个dimen的值,但是如果单位是dp或sp,则需要将其乘以density

如果是px,则不乘。并且getDimension返回float,getDimensionPixelOffset返回"下限"的int值.

getDimensionPixelSize则不管写的是dp还是sp还是px,都会乘以denstiy,返回"四舍五入"的int值.

切换Fragment时实现数据保持

replace方法会Fragment导致频繁的释放和创建,Fragment比较臃肿或者需要从网络加载数据这样就非常不好

instantiateItem从FragmentManager中查找Fragment,找不到就getItem新建一个,setPrimaryItem设置隐藏和显示,最后finishUpdate提交事务

Fragment fragment = (Fragment) mFragmentPagerAdapter.instantiateItem(mContainer, buttonView.getId());

mFragmentPagerAdapter.setPrimaryItem(mContainer, 0, fragment);

mFragmentPagerAdapter.finishUpdate(mContainer);

解决切换tab的时候重影现象

public void setMenuVisibility(boolean menuVisible) {

super.setMenuVisibility(menuVisible);

if (this.getView() != null)

this.getView().setVisibility(menuVisible ? View.VISIBLE : View.GONE);

}

Environment 常用方法

getDataDirectory(),获取 Android 数据目录

getDownloadCacheDirectory(),获取 Android 下载/缓存内容目录

getExternalStorageDirectory(),获取外部存储目录即 SDCard

getExternalStorageState(),获取外部存储设备的当前状态

getRootDirectory(),获取 Android 的根目录

Scrollview怎么判断是否滑倒顶部底部

滚动到顶部判断:getScrollY() == 0

滚动到底部判断:

View contentView = getChildAt(0);

contentView.getMeasuredHeight() <= getScrollY() + getHeight();

其中getChildAt表示得到ScrollView的child View,因为ScrollView只允许一个child view,所以contentView.getMeasuredHeight()表示得到子View的高度, getScrollY()表示得到y轴的滚动距离,getHeight()为scrollView的高度。当getScrollY()达到最大时加上scrollView的高度就的就等于它内容的高度了

Android Fragment嵌套使用存在的一些BUG

当使用Fragment去嵌套另外一些子Fragment的时候,我们需要去管理子Fragment,这时候需要调用ChildFragmentManager去管理这些子Fragment,由此可能产生的Exception主要是:

java.lang.IllegalStateException: No activity

当我们从一个Activity启动了一个Fragment,然后在这个Fragment中又去实例化了一些子Fragment,在子Fragment中去有返回的启动了另外一个Activity,即通过startActivityForResult方式去启动,这时候造成的现象会是,子Fragment接收不到OnActivityResult,如果在子Fragment中是以getActivity.startActivityForResult方式启动,那么只有Activity会接收到OnActivityResult,如果是以getParentFragment.startActivityForResult方式启动,那么只有父Fragment能接收(此时Activity也能接收),但无论如何子Fragment接收不到OnActivityResult,我们可以通过在子Fragment中以getParentFragment.startActivityForResult的方式来启动,然后在父Fragment中去接收数据,我们需要在子Fragment中提供一个方法,如:getResultData(Object obj),通过父Fragment中的子Fragment实例去调用这个方法,把相应的数据传过去,然后去更新子Fragment

布局文件后缀

swdp,如layout-sw600dp, values-sw600dp,这里的sw代表smallwidth的意思,当你所有屏幕的最小宽度都大于600dp时,屏幕就会自动到带sw600dp后缀的资源文件里去寻找相关资源文件,这里的最小宽度是指屏幕宽高的较小值,每个屏幕都是固定的,不会随着屏幕横向纵向改变而改变

wdp 如layout-w600dp, values-w600dp,带这样后缀的资源文件的资源文件制定了屏幕宽度的大于Ndp的情况下使用该资源文件,但它和swdp不同的是,当屏幕横向纵向切换时,屏幕的宽度是变化的,以变化后的宽度来与N相比,看是否使用此资源文件下的资源

hdp 如layout-h600dp, values-h600dp,这个后缀的使用方式和wdp一样,随着屏幕横纵向的变化,屏幕高度也会变化,根据变化后的高度值来判断是否使用hdp ,但这种方式很少使用,因为屏幕在纵向上通常能够滚动导致长度变化,不像宽度那样基本固定

Android 手机上获取物理唯一标识码

DEVICE_ID:可以同通过TelephonyManager.getDeviceId()获取,它根据不同的手机设备返回IMEI,MEID或者ESN码,但它在使用的过程中会遇到很多问题: 非手机设备、权限、BUG

MAC ADDRESS:我们也可以通过手机的Wifi或者蓝牙设备获取MAC ADDRESS作为DEVICE ID,但是并不建议这么做,因为并不是所有的设备都有Wifi,并且,如果Wifi没有打开,那硬件设备无法返回MAC ADDRESS

Serial Number:

在Android 2.3可以通过android.os.Build.SERIAL获取,非手机设备可以通过该接口获取

ANDROID_ID:是设备第一次启动时产生和存储的64bit的一个数,当设备被wipe后该数重置

ANDROID_ID似乎是获取Device ID的一个好选择,但它也有缺陷

Installtion ID : UUID通过在程序安装后第一次运行后生成一个ID实现的,但该方式跟设备唯一标识不一样,它会因为不同的应用程序而产生不同的ID,而不是设备唯一ID。因此经常用来标识在某个应用中的唯一ID(即Installtion ID),或者跟踪应用的安装数量

ViewPager取消预加载

setOffscreenPageLimit()这一个方法是设置预加载的个数,默认为1,但是当你设置为0的时候也会强行将它设置为1

public void setOffscreenPageLimit(int limit) {

if (limit < DEFAULT_OFFSCREEN_PAGES) {

Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to " +

DEFAULT_OFFSCREEN_PAGES);

limit = DEFAULT_OFFSCREEN_PAGES;

}

if (limit != mOffscreenPageLimit) {

mOffscreenPageLimit = limit;

populate();

}

}

attr和styleable的关系

attr不依赖于styleable,styleable只是为了方便attr的使用

而通过定义一个styleable,我们可以在R文件里自动生成一个int[],数组里面的int就是定义在styleable里面的attr的id

定义一个declare-styleable,在获取属性的时候为我们自动提供了一个属性数组。此外,我觉得使用declare-styleable的方式有利于我们我们把相关的属性组织起来,有一个分组的概念,属性的使用范围更加明确

多属性动画

构造多个对象Animator,( Animator可以ValueAnimator、ObjectAnimator和AnimatorSet)然后把它们放在一个AnimatorSet中。

ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f);

ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f);

AnimatorSet animSetXY = new AnimatorSet();

animSetXY.playTogether(animX, animY);

animSetXY.start();

用一个ObjectAnimator对象加多个PropertyValuesHolder:

PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f);

PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f);

ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvyY).start();

使用ViewPropertyAnimator

myView.animate().x(50f).y(100f);

用一个ObjectAnimator实例,实现View既可以缩小、又能够淡出(3个属性scaleX,scaleY,alpha)

public void rotateyAnimRun(final View view)

{

ObjectAnimator anim = ObjectAnimator//

.ofFloat(view, "zhy", 1.0F, 0.0F)//

.setDuration(500);//

anim.start();

anim.addUpdateListener(new AnimatorUpdateListener()

{

@Override

public void onAnimationUpdate(ValueAnimator animation)

{ // 获取当前值

float cVal = (Float) animation.getAnimatedValue();

view.setAlpha(cVal);

view.setScaleX(cVal);

view.setScaleY(cVal);

}

});

}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值