Android知识点笔记

作者: MigrationUK | 来源:发表于2017-12-08 15:35 被阅读44次
    1. dispatchMessage() 分发消息三种情况
      1. Message对象的callback不为空(runnable),交给callback处理
      2. handler的callback不为空,交给callback处理(如果你消息自己有callback的话,就会优先执行你的消息的callback)
      3. 前两种都没有的情况下交给handleMessag去处理
    2. Message的Obtain()/recycleUnchecked()

    3. DialogFragment至少重写下面一个方法
      1. onCreateView:自己通过XML定义布局
      2. onCreateDialog:使用系统内置对话框比如AlertDialog
    4. swapCursor vs changeCursor
    5. LayoutAnimation vs LayoutTransition
    6. CursorTreeAdapter的使用简介
    7. 带你看懂LayoutInflater中inflate方法
    8. 自定义View构造函数参数
      1. 一个参数:一般在直接New一个View的时候调用
      2. 两个参数:一般在layout文件中使用的时候会调用,关于它的所有属性(AttributeSet)(包括自定义属性,直接引用的Style资源)都会包含在attrs中传递进来
      3. 三个参数:默认的Style是指它在当前Application或Activity所用的Theme中的默认Style,且只有在明确调用的时候才会生效(AttributeSet未找到则从这里找)
      4. 四个参数:API21的时候才添加上,当第三个参数不生效时才有作用
      5. 优先级从高到低依次是:直接在layout中设置View的XML属性值(AttributeSet)> 设置View的style属性 > defStyleAttr > defStyleRes
    9. Android安全机制分为三层
      1. 最基础的一层,数据分为system和data两个区。其中system是只读的,data用来存放应用自己的数据,这保证了系统数据不会被随意改写
      2. 第二层用来使应用之间的数据相互独立。每个应用都会有一个user id和group id,只有相同的user id才能问它们的数据。通过对apk签名来标识自己。签名和uid构成了双重的保证
      3. 第三个层次就是权限体系
    10. 调用的系统API接口,有3种目录可以给我们写入文件
      1. 应用私有存储(内置存储)不需要申请
        • Context.getFileDir():/data/data/应用包名/files/ 对应着App下清除数据
        • Context.getCacheDir():/data/data/应用包名/cache/ 对应着清除缓存
      2. 应用扩展存储(SD卡)API < 19:需要&API >= 19:不需要
        • Context.getExternalFilesDir():SDCard/Android/data/应用包名/files/
        • Context.getExternalCacheDir():SDCard/Android/data/应用包名/cache/
      3. 公共存储(SD卡)需要申请
        • Environment.getExternalStorageDirectory():SDCard/文件夹名字/
    11. Bitmap 在内存当中占用的大小其实取决于
      1. 色彩格式,eg:如果是 ARGB8888 是像素4个字节,如果是 RGB565 是2个字节
      2. 原始文件存放的资源目录(是 hdpi 还是 xxhdpi 可不能傻傻分不清楚哈)
      3. 目标屏幕的密度(所以同等条件下,红米在资源方面消耗的内存肯定是要小于三星S6的)
    12. 解决屏幕旋转(状态发生变化)状态不能保持的问题
      1. 不好的实践:保存整个Activity使用设置android:configChanges属性,不止是屏幕旋转。比如修改设备默认语言,修改设备默认字体比例等都可会引起配置改变
      2. 已经被弃用的方法(API 13):重写onRetainNonConfigurationInstance()、getLastNonConfigurationInstance()方法
      3. 使用onSaveInstanceState() 、onRestoreInstanceState()进行数据保存与恢复
      4. 推荐的方法:在Retained Fragment中管理对象
        1. 扩展Fragment类,并声明对有状态对象的引用(onAttach引用Activity)
        2. 创建Fragment时调用setRetainInstance(boolean)
        3. 将片段添加到Activity
        4. 当Activity重新启动时,使用FragmentManager检索片段
    13. 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()
    14. TouchEvent事件,低8位表示touch事件的具体动作,比如按下,抬起,滑动,还有多点触控时的按下,抬起,这个和单点是区分开的
      1. getAction:触摸动作的原始32位信息,包括事件的动作,触控点信息
      2. getActionMask:触摸的动作,按下,抬起,滑动,多点按下,多点抬起
      3. getActionIndex:触控点信息
    15. TypedArray中的函数是获取自定义属性的,Resources中的函数是获取android预置属性的
      1. getDimension()是基于当前DisplayMetrics进行转换,获取指定资源id对应的尺寸。函数的返回值是float,像素肯定是int
      2. getDimensionPixelSize()与getDimension()功能类似,不同的是将结果转换为int,并且小数部分四舍五入
      3. getDimensionPixelOffset()功能类似,不同的是将结果转换为int,并且偏移转换(offset)是直接截断小数位,即取整(其实就是把float强制转化为int)
    16. 系统属性SystemProperty
      1. 通过命令adb shell getprop查看手机上所有属性状态值
      2. 属性名称以“ro.”开头,那么这个属性被视为只读属性。一旦设置,属性值不能改变
      3. 属性名称以“persist.”开头,当设置这个属性时,其值也将写入/data/property
      4. 属性名称以“net.”开头,当设置这个属性时,“net.change”属性将会自动设置,以加入到最后修改的属性名
    17. save&saveLayer
      1. save方法可以保存当前的matrix and clip,并且在restore把它恢复,一些平移,旋转,缩放等操作都会影响Canvas的matrix,所以save操作一般可以保存这些信息以及clip信息
      2. saveLayer则强大很多,它相当于另外起一张干净图层,并在上面进行绘制操作,然后在restoreToCount的时候,把刚才所绘制的重新绘制在原本的Canvas上。当时正如所知的那样,它会绘制两次,所以消耗是十分巨大
    18. 代码中获取attr属性的值
      1. 在xml里,我们可以简单的引用attr属性值,例如:
        android:background="?attr/colorPrimary"
        android:minHeight="?attr/actionBarSize"
      2. 代码中获取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;
      
    19. Activity启动过程
      Activity启动过程
    20. SparseArray
      • SparseArray 在某些条件下性能更好,主要是因为它避免了对key的自动装箱,内部是通过两个数组来进行数据存储的,一个存储key,另外一个存储value,但是由于其添加、查找、删除数据都需要先进行一次二分查找,所以在数据量大的情况下性能并不明显,将降低至少50%。
      • 数据量不大,最好在千级以内
      • key必须为int类型,这中情况下的HashMap可以用SparseArray代替:
    21. ArrayMap
      • ArrayMap是一个<key,value>映射的,它设计上更多的是考虑内存的优化,内部是使用两个数组进行数据存储,一个数组记录key的hash值,另外一个数组记录Value值,它和SparseArray一样,也会对key使用二分法进行从小到大排序,在添加、删除、查找数据的时候都是先使用二分查找法得到相应的index,然后通过index来进行添加、查找、删除等操作,所以,应用场景和SparseArray的一样,如果在数据量比较大的情况下,那么它的性能将退化至少50%。
      • 如果key的类型已经确定为int类型,那么使用SparseArray,因为它避免了自动装箱的过程,如果key为long类型,它还提供了一个LongSparseArray来确保key为long类型时的使用
      • 如果key类型为其它的类型(String),则使用ArrayMap
      • 两个数据结构都适合数据量不是特别大的情况
    22. 编译时候加上(据说编译比较快)
       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
           }
         }
      }
      
    23. ExecutorService的关闭方法
      • shutdown():将线程池状态置为SHUTDOWN,并不会立即停止
      • shutdownNow():将线程池状态置为STOP,企图立即停止,事实不一定
      • awaitTermination(): 当前线程阻塞,直到等所有已提交的任务(包括正在跑的和队列中等待的)执行完
    24. Service
      • 启动服务的需要通过 stopSelf() 自行停止,或其他组件调用 stopService()
      • onRebind()方法调用时机:
        • onUnbind()方法返回值为true
        • 启动服务同时和绑定服务,当Activity退出的时候,Service的onUnbind()方法就会被调用
    25. 内容提供着权限有:
      1. 统一读写提供程序级别权限
      2. 单独的读取和写入提供程序级别权限
      3. 路径级别权限
      4. 临时权限
    26. Android 6.0 Marshmallow的运行时权限
      1. 检查系统版本号:对于6.0开始的版本,才需要做运行时的权限检查
      2. 检查申请的权限:checkSelfPermission(Manifest.permission.xxx)
      3. 解释申请的权限:shouldShowRequestPermissionRationale()
      4. 执行申请权限操作:requestPermissions()
      5. 处理权限申请的结果:onRequestPermissionsResult()
    27. Android安全机制
      1. 进程沙箱隔离机制
      2. 应用程序签名机制
      3. 权限声明机制
      4. 访问控制机制
      5. 进程通信机制
    28. android中延迟执行某个任务

      • 倒计时类
        • 用CountDownTimer
      • 延迟类
        • CountDownTimer,可巧妙的将countDownInterval设成和millisInFuture一样,这样就只会调用一次onTick和一次onFinish
        • handler.sendMessageDelayed,可参考CountDownTimer的内部实现,简化一下,个人比较推荐这个
          TimerTask,代码写起来比较乱
          Thread.sleep,感觉这种不太好
      • 定时类
        • 参照延迟类的,自己计算好要延迟多少时间
          handler.sendMessageAtTime
          AlarmManager,适用于定时比较长远的时间,例如闹铃
    29. setBackgroundXXX的用法

      • setBackgroundDrawable 的参数为Drawable对象
      • setBackgroundColor 的参数为Color对象,比如说Color.Red为红色,或Color.rgb(255,0,0)
      • setBackgroundResource 的参数为资源ID,比如说R.drawable.icon
    30. getDimension,getDimensionPixelOffset和getDimensionPixelSize

      • getDimension和getDimensionPixelOffset的功能类似,都是获取某个dimen的值,但是如果单位是dp或sp,则需要将其乘以density
        如果是px,则不乘。并且getDimension返回float,getDimensionPixelOffset返回"下限"的int值.
      • getDimensionPixelSize则不管写的是dp还是sp还是px,都会乘以denstiy,返回"四舍五入"的int值.
    31. 切换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);
        }
        
    32. Environment 常用方法

      • getDataDirectory(),获取 Android 数据目录
      • getDownloadCacheDirectory(),获取 Android 下载/缓存内容目录
      • getExternalStorageDirectory(),获取外部存储目录即 SDCard
      • getExternalStorageState(),获取外部存储设备的当前状态
      • getRootDirectory(),获取 Android 的根目录
    33. 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的高度就的就等于它内容的高度了

    34. 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
    35. 布局文件后缀

      • sw<N>dp,如layout-sw600dp, values-sw600dp,这里的sw代表smallwidth的意思,当你所有屏幕的最小宽度都大于600dp时,屏幕就会自动到带sw600dp后缀的资源文件里去寻找相关资源文件,这里的最小宽度是指屏幕宽高的较小值,每个屏幕都是固定的,不会随着屏幕横向纵向改变而改变
      • w<N>dp 如layout-w600dp, values-w600dp,带这样后缀的资源文件的资源文件制定了屏幕宽度的大于Ndp的情况下使用该资源文件,但它和sw<N>dp不同的是,当屏幕横向纵向切换时,屏幕的宽度是变化的,以变化后的宽度来与N相比,看是否使用此资源文件下的资源
      • h<N>dp 如layout-h600dp, values-h600dp,这个后缀的使用方式和w<N>dp一样,随着屏幕横纵向的变化,屏幕高度也会变化,根据变化后的高度值来判断是否使用h<N>dp ,但这种方式很少使用,因为屏幕在纵向上通常能够滚动导致长度变化,不像宽度那样基本固定
    36. 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),或者跟踪应用的安装数量
    37. 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();
        }
      }
      
    38. attr和styleable的关系

      • attr不依赖于styleable,styleable只是为了方便attr的使用
      • 而通过定义一个styleable,我们可以在R文件里自动生成一个int[],数组里面的int就是定义在styleable里面的attr的id
      • 定义一个declare-styleable,在获取属性的时候为我们自动提供了一个属性数组。此外,我觉得使用declare-styleable的方式有利于我们我们把相关的属性组织起来,有一个分组的概念,属性的使用范围更加明确
    39. 多属性动画

      • 构造多个对象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);  
          }  
         });  
        }  
        

    相关文章

      网友评论

        本文标题:Android知识点笔记

        本文链接:https://www.haomeiwen.com/subject/zgbeixtx.html