Android Training 的整理和总结

来源:互联网 发布:西安交大网络公开课 编辑:程序博客网 时间:2024/06/05 19:01

概述:

最近花了一段时间去好好重温了下Android Training,发现还挺有收获的,就希望能把它整理总结一下。一些过于简单或者比较偏门的内容就没有提及,关于Android测试部分,我希望做更多的尝试和实践之后再进行整理和总结。

具体内容:

  • Fragment和Activity之间有回调时,要在Fragment的onAttach时进行验证

    try {mCallback = (OnItemSelectedListener) activity;} catch (ClassCastException e) {throw new ClassCastException(activity.toString()+ " must implement OnItemSelectedListener");}
  • Transition and scenes仅支持19(4.4.2)以上,14(4.0)到19用animateLayoutChanges;每一个scenes都是一个Layout(基本可以这么说,虽然可以动态创建scenes),而transition的作用就是从一个scenes转换到另一个scenes,转换效果已有的有fade、moves、resize(当然你也可以自定义transition),尽量避免在adapterview和包含text的view里面使用。(局限还很多,不太实用)

  • 传输数据时尽量减少电量损耗

    1. 预取数据
    2. 使用批传输和批连接
    3. 减少连接,重用连接
    4. 无法避免使用轮询时,使用不精确的重复时钟
    5. 处理下载缓存和连接请求之间的矛盾
    6. 根据连接类型来修改下载模式(一般wifi拥有高带宽和更低的电量损耗)
    7. 高效下载例子
  • ContentProviderClient和ContentResolver的区别总结:Client的获取方法getContentResolver().acquireContentProviderClient(authority);针对不同ContentProvider的多次调用,使用ContentResolver;针对相同ContentProvider的多次调用,使用Client,但是记得释放 .release()

  • SyncAdapter的使用方法

    1. 创建、绑定(服务)和声明Authenticator(这个就是账号和授权问题)
    2. 必须配合ContentProvider使用
    3. 创建同步适配器,绑定服务,增加元数据资源和声明
    4. 在APP入口Activity初始化SyncAdapter,同步方式有即时同步(服务器端数据发送变化,使用GMC的方式或者是轮询的方式;设备数据发生变化),(自定义)周期性,系统发送网络消息的时候
  • SyncAdapter的使用场景

    1. 同步服务器数据到设备
    2. 同步设备数据到服务器
    3. 需要注意的点,最好不要用该同步获取需要及时反馈数据的请求,SyncAdapter是单实例,一般在多用户的情况下才需要使用并行的SyncAdapter
    4. SyncAdapter例子
  • 通过管理配置文件保证兼容性

    1. 对于隐式intent,要使用resolveActivity()方法
    2. 对于文件分享,要使用FileProvider,避免使用文件的uri
    3. 配置文件例子
  • ViewPager两个Adapter的使用场景和优劣

    1. FragmentPagerAdapter:用于子屏幕只有固定且少量的页面
    2. FragmentStatePagerAdapter:用于页面不确定的情况,每次切换到别的页面,都会destroy当前的fragment,减少内存使用
  • 需要手动处理Back行为的情况

    1. 当用户通过notification, app widget, navigation drawer进入深层次的activity时
    2. 用户在fragment间切换的某些情况
    3. 通过webview浏览网页时
  • 当SnackBar配合CoordinatorLayout使用时,有下面两个额外的功能

    1. 用户可以滑动SnackBar使之消失
    2. 如果SnackBar出现的地方有别的View,会把该View上推,而不会覆盖在上面
  • 自定义View

    1. 当View的某些内容发生变化时,需要调用invalidate来通知系统对这个View进行redraw,当某些元素改变会引起组件大小或形状变化时,需要调用requestLayout方法
    2. onDraw里的Canvas处理绘制什么,Paint处理如何绘制
    3. 绘制文字用drawTest,绘制基本图形使用drawRect等,绘制复杂图形使用Path类,定义渐变使用LinearGradient对象,绘制图片使用drawBitmap绘制文字用drawTest,绘制基本图形使用drawRect等,绘制复杂图形使用Path类,定义渐变使用LinearGradient对象,绘制图片使用drawBitmap
    4. 优化自定义View
      A. 在onDraw里面不要做内存分配的事情,在初始化或者动画间隙期间做分配内存的动作
      B. 减少onDraw被调用的次数,一般都是调用了invalidate导致重绘,因此减少调用invalidate的次数,尽量调用含有4个参数的invalidate方法,无参的invalidate会强制重绘整个view
      C. requestLayout会使得AndroidUI系统去遍历整个View的层级来计算每一个view的大小。如果找到有冲突的值,它会重新计算好几次,所以尽量保持View层级是扁平化
      D. 考虑写一个自定义的ViewGroup来执行复杂UI的layout操作。与内置的view不同,自定义的view可以使得程序仅仅测量这一部分,避免了遍历整个view的层级结构来计算大小
    5. 自定义View例子
  • 创建向后兼容的UI(其实就是使用设计模式的六大原则)

    1. 创建抽象的UI接口,决定应用需要的功能和特定的API接口(abstract UI class)
    2. 抽象出一个该UI的相应帮助方法类,帮助你创建对应版本的UI实现(helper class)
    3. 使用新的API实现UI,继承实现抽象的UI类和helper类
    4. 决定一个替代方案,并使用旧的API实现UI,继承实现抽象的UI类和helper类
    5. 在helper class添加切换逻辑,其实就是根据版本选择不同的实现方案
    6. 在xml中的layout layout-v11提供两种UI实现的界面布局
    7. 在Activity中使用helper class获取helper对象,并添加相应UI
    8. 兼容UI例子
  • 管理系统的UI主要是指系统栏(状态栏和导航栏),主要使用场景是沉浸式应用

    1. 淡化系统栏,android在4.0后有自带的方法
    2. 隐藏状态栏,4.0前后有不同的处理方法,注意同步状态栏和Action Bar的变化
    3. 隐藏导航栏,android在4.0后有自带的方法
    4. 响应系统UI的可见性变化监听器

      View decorView = getWindow().getDecorView();decorView.setOnSystemUiVisibilityChangeListener
    5. 沉浸方式包含粘性(IMMERSIVE)和非粘性(IMMERSIVE_STICKY),仅在4.4(包含)以后使用
      A. 使用场景:图书浏览器和新闻杂志阅读器,因为用户可能会经常访问Action Bar和一些UI控件,又不希望在翻页的时候有其他的东西进行干扰
      B. 打造一款真正的沉浸式应用,你希望屏幕边缘的区域也可以与用户进行交互,并且用户也不会经常访问系统UI
      C. 打造一款视频播放器,并且需要少量的用户交互操作,可能不需要沉浸式,使用淡化或者隐藏系统栏即可
      D. 粘性与非粘性的区别在于:粘性沉浸当用户向内滑动使系统栏是临时显示(transient),并处于半透明状态,并且标签不会被清除,系统UI可见性监听器也不会被触发;而非粘性是保持显示,清除标签,并触发可见性监听器
    6. 粘性沉浸式例子
  • 使用触摸手势

    1. 这里介绍得太粗糙了,还是找个时间结合自定义View再深入整理和总结
    2. 这里介绍了一种扩展子视图的可触摸区域,跟简单的设定padding有点区别,还是挺实用的
    3. 触摸手势例子
  • 处理键盘输入

    1. 可以指定键盘输入的类型,如纯数字或邮箱格式等
    2. 可以开启拼写建议和其他行为
    3. 可以指定输入法的行为,通过定义View.OnEditorActionListener来监听动作按钮的按压,在监听器中要监听EditorInfo类中定义的适合的IME action ID
    4. 根据需要显示输入法,并制定UI的响应方式
    5. 支持硬键盘导航主要用到xml里面的属性:android:nextFocusForward, nextFocusUp, nextFocusDown, nextFocusLeft, nextFocusRight
    6. 处理键盘的动作,可以通过实现KeyEvent.Callbak接口的回调方法,处理单个按钮事件最好使用onKeyUp,因为onKeyDown在用户点击并按住按钮不放的情况下,会被调用多次
  • 管理设备的唤醒状态

    1. 保持屏幕的常亮
      A. 在且仅在Activity中调用 getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
      B. 在xml里使用android:keepScreenOn
      C. 动态关闭屏幕 getWindow.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    2. 保持CPU运行和制定重复闹钟
  • 管理应用的内存

    1. Android系统管理内存
      A. 每一个App进程都是从一个叫Zygote的进程中fork出来的,该进程会在系统启动时开启并加载通用的framework代码和资源,这就使得大多数的RAM pages可以在应用的所有进程中进行共享
      B. Dalvik heap有上限,逻辑上heap size和实际物理上的内存数量是不等的
      C. Android不会在用户切换应用时做交换内存的操作
    2. 自己的应用管理内存
      A. 处理Services资源,及时关闭,同时注意当这个service完成任务后因为停止service失败而引起的内存泄漏
      B. UI隐藏时释放内存,应用仅会在所有UI组件都被隐藏的时候接收到onTrinMemory()回调方法(只在Activity有),你应该在参数是TRIM_MEMORY_UI_HIDDEN时,释放UI资源
      C. 仅保存适配当前屏幕设备分辨率的Bitmap数据
      D. 使用在Android更高效的容器如SparseArray, SparseBooleanArray, LongSparseArray
      E. 避免使用Enums,它的内存消耗通常是static constants的2倍,每一个Java类花销500 bytes,每一个类的实例花销12-16 bytes,往HashMap添加一个Entry需要额外消化32 bytes的entry对象,所有HashMap的实现方式更加消耗内存
      F. 使用ProGuard
      G. 使用zipalign
      H. 使用多进程
    3. 内存管理的例子
  • 提升layout的性能

    1. 嵌套使用layout_weight参数的LinearLayout的子元素需要被测量两次
    2. 使layout层级扁平化,使用Lint检测
    3. 使用include和merge标签重用layout,ViewStub提供按需加载layout功能(暂不支持merge标签的layout)
  • 优化电池寿命

    1. 通过BatteryManager判断和监听充电状态
    2. 通过BatteryManager判断和监听电池电量
    3. 通过Sticky Intent广播来判断底座状态、类型和监听相应的改变
    4. 通过ConnectivityManager来判断当前网络状态和类型,并监听连接的变化
    5. 按需切换注册在Manifest文件的静态Receiver的开启关闭状态,使用情景如:确定网络连接已断开,关闭除监听网络状态变化的接收器之外的其它所有接收器;网络连接重新建立,停止监听网络连接的改变,并在执行需要联网的操作前判断当前网络是否可用,关键代码如下:
      ComponentName receiver = new ComponentName(context, myReceiver.class); PackageManager pm = context.getPackageManager();pm.setComponentEnabledSetting(receiver, PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP);
  • 多线程操作

    1. 定义线程类的方法,实现Runnable接口,并实现里面的run方法,通过start方法调用
    2. 新线程默认有着和UI线程一样的优先级,可以通过在run方法里面的Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUD); 设置线程的优先级,这里把它设成了background
    3. 创建多线程管理器ThreadPoolExecutor类
      A. 使用线程安全的单例模式定义该类(静态内部类)
      B. 创建线程池的方法 ThreadPoolExecutor mDecodeThreadPool = new ThreadPoolExecutor(INITIAL_NUMBER_OF_CORES,MAX_NUMBER_OF_CORES,KEEP_ALIVE_TIME,KEEP_ALIVE_TIME_UNIT,mDecodeWorkQueue); 其中NUMBER_OF_CORES可以用Runtime.getRuntime().availableProcessors()获取,KEEP_ALIVE_TIME_UNIT可以用TimeUnit.SECONDS获取,mDecodeWorkQueue可以用new LinkedBlockingQueue()获取
      C. 启动线程的方法 mDecodeThreadPool.execute(getRunnable()); //Runnable实例
      D. 中断正在执行的线程 thread.interrupt(); // 需要放在同步代码块中执行,即在synchronized方法里面,并且该方法只能停止那些处于等待状态的线程,不能中断那些占据CPU或耗时的连接网络的任务
      E. 与UI线程的通信 在线程池类里面定义一个处于UI线程的Handler,即 new Handler(Looper.getMainLooper),并实现handleMessage方法,主要是在UI线程更新UI,当线程需要和UI线程通信时,先构造一个Message,Messge completeMessage = mHandler.obtainMessage(what,object); 然后把它发送给目标 completeMessage.sendToTarget(); 此处的String what算是一种状态字,对应于handleMessage方法里面的状态,根据不同的状态进行不同的处理,而object就是当前线程发送给UI线程的对象信息,就是实际通信的内容
  • 安全要点

    1. 数据存储
      A. 在内部存储的文件只有自己的应用能访问,和其他应用共享文件,应该使用Content Provider,想对敏感数据进行保护,应该使用保存在keystore而不是在设备上的密钥来加密文件,但是这样方法还是无法防止通过root权限来查看用户输入的密码
      B. 外部存储是所有应用都可以修改的,强烈建议应用在动态加载前不要把可执行文件或者class文件存储到外部存储
      C. Content Providers 不打算让其他应用访问并且仅在自己的应用中共享数据,应该设置android:exported=false; CP一般都会声明使用权限,在permission里使用android:protectionLevel:signature;在访问CP的时候,使用参数化的查询方法,如query(), update(),防止潜在的SQL注入
    2. 使用网络
      A. 使用IP网络,尽量使用HTTPS协议进行网络传输,授权且加密的套接层级别的通信可以使用SSLSocket类来实现
      B. 处理用户数据,最小化获取敏感数据用户个人数据的API使用
      C. WebView谨慎开启JavaScript,addJavaScriptInterface()也仅暴露给应用内包含的Js,当通过WebView访问敏感数据时,使用clearCache()来删除任何存储到本地的文件
      D. 处理证书,可能的话,用户名和密码不应该保存到设备上,应该给一个短暂的特定服务的授权令牌。
      E. 使用加密,使用Cipher类中提供的AES或者RSA,在初始化加密密钥(KeyGenerator)时,使用安全的随机数生成器(SecureRandom)
      F. 进程通信,传统的Linux技术实现IPC,即网络socket和文件,我们应该选择使用Android系统的IPC功能,如Intent, Binder,Messenger和BroadcastReceiver
      G. 应该避免动态加载代码,因为考虑到代码注入和代码篡改,这样做会增加应用暴露的可能,同时增加版本管理和应用测试的复杂性

总结:

重温这份Training,是为了从广度上把握Android整体架构、功能和使用场景,接下来就需要更深入地了解Android系统的各部分,并整理归纳。

0 0
原创粉丝点击