《Android秘籍.第三卷》

9 篇文章 0 订阅
1 篇文章 0 订阅

《Android秘籍.第三卷》

目录

《Android秘籍.第三卷》

《数据存储篇》

Android中提供哪些数据持久存储的方法。

Java中的I/O流(输入输出流)。

SharePreferences适用情形?使用中需要注意什么?

了解SQLite中的事务处理吗?是如何做的?

使用SQLite做批量操作有什么好的方法吗?

如果现在要删除SQLite中表的一个字段如何做?

使用SQLite时会有哪些优化操作?

《View篇》

 

MotionEvent是什么?包含几种事件?什么条件下会产生?

scrollTo()和scrollBy()的区别?

Scroller中最重要的两个方法是什么?主要目的是?

谈一谈View的事件分发机制?

如何解决View的滑动冲突?

谈一谈View的工作原理?

View的工作流程

MeasureSpec(测量规格)是什么?有什么作用?

自定义View/ViewGroup需要注意什么?

onTouch()、onTouchEvent()和onClick()关系?

SurfaceView和View的区别?

invalidate()和postInvalidate()的区别?

《Bitmap篇》

 

加载图片的时候需要注意什么?

LRU算法的原理?

Android中缓存更新策略?

《Animation篇》

Android中有哪几种类型的动画?

帧动画在使用时需要注意什么?

View动画和属性动画的区别?

View动画为何不能真正改变View的位置?而属性动画为何可以?

属性动画插值器和估值器的作用?

《Drawable等资源篇》

了解哪些Drawable?适用场景?

mipmap系列中xxxhdpi、xxhdpi、xhdpi、hdpi、mdpi和dpi存在怎样的关系?

dp、dpi、px的区别?

res目录和assets目录的区别?


数据存储篇


Android中提供哪些数据持久存储的方法。

  • Android中,可供选择的存储方式有SharedPreferences、文件存储、SQLite数据库方式、内容提供器(Content provider)和网络。


Java中的I/O流(输入输出流)。

  • Java中的流分为两种,一种是字节流,另一种是字符流,分别由四个抽象类来表示(每种流包括输入和输出两种所以一共四个):所有输入流类都是抽象类InputStream(字节输入流)或抽象类Reader(字符输入流)的子类;而所有输出流都是抽象类OutputStream(字节输出流)或抽象类Writer(字符输出流)的子类。


SharePreferences适用情形?使用中需要注意什么?

  • 保存登录用户名密码等情形,应注意多进程并发读的时候数据可能不准确。
  • 需要注意:getSharedPreferences(“User”, Context.MODE_PRIVATE)方法中第二个参数需要了解Android的四种枚举方式下面是详细的解释: 
  • 私有模式 
  • Context.MODE_PRIVATE 的值是 0; 
  • ①只能被创建这个文件的当前应用访问 
  • ②若文件不存在会创建文件;若创建的文件已存在则会覆盖掉原来的文件
  • 追加模式 
  • Context.MODE_APPEND 的值是 32768; 
  • ①只能被创建这个文件的当前应用访问 
  • ②若文件不存在会创建文件;若文件存在则在文件的末尾进行追加内容
  • 可读模式 
  • Context.MODE_WORLD_READABLE的值是1; 
  • ①创建出来的文件可以被其他应用所读取
  • 可写模式 
  • Context.MODE_WORLD_WRITEABLE的值是2 
  • ①允许其他应用对其进行写入。

 

了解SQLite中的事务处理吗?是如何做的?

  • 事务(Transactioin)是一个对数据库执行工作单元。事务(Transction)是以逻辑顺序完成的工作单位或序列,可以是由用户手动操作完成,也可以是由某种数据库程序自动完成。
  • 事务控制  
  •   ·BEGIN TRANSACTION:开始事务处理。    
  • ·COMMIT:保存更改,或者可以使用END TRANSACTION命令;    
  • ·ROLLBACK:回滚所做的更改。    
  •  事务控制命令只与DML命令INSERT、UPDATE和DELETE一起使用。它们不能在创建表或删除表时使用,因为这些操作在数据库中是自动提交的
  • 使用SQLiteDatabase的beginTransaction()方法可以开启一个事务,程序执行到endTransaction() 方法时会检查事务的标志是否为成功,如果程序执行到endTransaction()之前调用了setTransactionSuccessful() 方法设置事务的标志为成功则提交事务,如果没有调用setTransactionSuccessful() 方法则回滚事务。多用于大量数据操作时,能明显减少耗时。

 


使用SQLite做批量操作有什么好的方法吗?

即使用事务处理进行优化,默认SQLite的数据库插入操作,如果没有采用事务的话,它每次写入提交,就会触发一次事务操作,而这样几千条的数据,就会触发几千个事务的操作,这就是时间耗费的根源


如果现在要删除SQLite中表的一个字段如何做?

SQLite目前还不支持drop column,所以必须想出另外一种方法来进行表字段的删除。

如下sql语句会复制一个和record表一样表结构的temp表出来,但是我们想要的是去除某一个字段(例如去除record表中的name字段,就不要复制它就好了),所以sql语句如下:

create table temp as select recordId, customer, place, time from record where 1 = 1;  

这样复制出来的表就会缺少“name”字段,然后我们删除旧表并修改新表名即可。


使用SQLite时会有哪些优化操作?

  • 编译SQL语句(重用SQLiteStatement)
  • 显示使用事务(降低批量数据库更新文件打开关闭次数)
  • 简历索引(快速找到表中对应记录)
  • 查询数据优化
  • ContentValues的容量调整
  • 及时关闭Cursor
  • 耗时异步化

 

View篇


MotionEvent是什么?包含几种事件?什么条件下会产生?

  • MotionEvent是事件传递中一个重要的概念(事件类型)。
  • MotionEvent.ACTION_DOWN:当屏幕检测到第一个触点按下之后就会触发到这个事件。
  • MotionEvent.ACTION_MOVE:当触点在屏幕上移动时触发,触点在屏幕上停留也是会触发的,主要是由于它的灵敏度很高,而我们的手指又不可能完全静止(即使我们感觉不到移动,但其实我们的手指也在不停地抖动)。
  • MotionEvent.ACTION_POINTER_DOWN:当屏幕上已经有触点处于按下的状态的时候,再有新的触点被按下时触发。
  • MotionEvent.ACTION_POINTER_UP:当屏幕上有多个点被按住,松开其中一个点时触发(即非最后一个点被放开时)触发。
  • MotionEvent.ACTION_UP:当触点松开时被触发。
  • MotionEvent.ACTION_OUTSIDE: 表示用户触碰超出了正常的UI边界.
  • MotionEvent.ACTION_SCROLL:android3.1引入,非触摸滚动,主要是由鼠标、滚轮、轨迹球触发。
  • MotionEvent.ACTION_CANCEL:不是由用户直接触发,由系统在需要的时候触发,例如当父view通过使函数onInterceptTouchEvent()返回true,从子view拿回处理事件的控制权时,就会给子view发一个ACTION_CANCEL事件,子view就再也不会收到后续事件了


scrollTo()和scrollBy()的区别?

  • scrollBy()也调用了scrollTo()方法,实现了基于当前位置的滑动,而scrollTo()是基于所传参数的绝对滑动


Scroller中最重要的两个方法是什么?主要目的是?

  • Scroller方法一共可以分三步:最重要是后两个方法
  • 创建一个Scroller对象,一般在View的构造器中创建:
  • 重写View的computeScroll()方法
  • 调用startScroll()方法,startX和startY为开始滚动的坐标点,dx和dy为对应的偏移量:
  • startScroll()设置好了一堆初始值,之后调用了invalidate()让View重新绘制,这里又有一个很重要的点,在draw()中会调用computeScroll()这个方法!


谈一谈View的事件分发机制?

  • Android事件分发机制主要由“事件分发”—>“事件拦截”—>“事件响应”这三步来进行逻辑控制的

ViewGroup:

  • 事件开始>dispatchTouchEvent问自己是否需要拦截此事件?
  • true:拦截事件,直接交给自己的onTouchEvent方法去处理事件,事件终止
  • false:不拦截,交给子控件去处理.

View:

  • 传递到view控件:View下没有子控件
  • true:当前view处理该事件,事件终止
  • false:不处理当前事件,向上回传(传到上层的onTouchEvent)
  • 如果最高层的onTouchEvent收到了子控件回传的事件,返回true则处理该事件,返回false,则不处理事件,事件丢失
  • 事件分发:public boolean dispatchTouchEvent(MotionEvent ev):当监听到有触发事件时,首先由Activity进行捕获,然后事件就进入事件分发的流程。Activity本身没有事件拦截,从而将事件传递给最外层的View的dispatchTouchEvent(MotionEvent ev)方法,该方法将对事件进行分发。return true : View消费所有事件。return false :停止分发,交由上层控件的onTouchEvent方法进行消费,如果本层控件是Activity,那么事件将被系统消费、处理。super.dispatchTouchEvent(ev): 将事件交由本层的事件拦截onInterceptTouchEvent方法处理。
  • 事件拦截:public boolean onInterceptTouchEvent(MotionEvent ev):return true: 对事件拦截,交由本层的onTouchEvent进行处理,return false: 不拦截,分发到子View,由子View的dispatchTouchEvent方法处理。super.onInterceptTouchEvent(ev):默认表示事件拦截,交由本层的onTouchEvent进行处理。
  • 事件响应:public boolean onTouchEvent(MotionEvent ev):return true: 表示onTouchEvent处理完事件后消费了此次事件。return false: 不响应事件,不断的传递给上层的onTouchEvent方法处理,直到某个View的onTouchEvent返回true,则认为该事件被消费。如果到最顶层View还是返回false,那么该事件不消费,将交由Activity的onTouchEvent进行处理。return: super.onTouchEvent,不响应事件,结果与return返回false一样。


如何解决View的滑动冲突?

外部拦截:可以在父布局中将onInterceptTouchEvent的返回值设为true进行拦截

内部拦截:类似反射的方式进行拦截,稍显复杂。需要配合requestDisallowInterceptTouchEvent进行拦截


谈一谈View的工作原理?

View的工作原理不知道该从何说起,可以简单讲下View的三个过程,几个常见回调方法,以及两个重要概念。

三个过程:

  • measure:测量View的宽和高
  • layout:确定View在父控件中的放置位置
  • draw:负责将View绘制在屏幕上。

常见回调方法:

  • 构造方法
  • onAttachToWindow:在包含View的Activity启动时调用
  • onDetachFromWindow:在包含View的Activity退出或者View被remove时回调
  • onVisibilityChanged:当View的可见状态发生改变时调用

两个重要概念:

  • ViewRoot:连接WindowManager(外界访问Window的入口)和DecorView(顶级View)的纽带,View的三大流程均是通过ViewRoot来完成的。
  • DecorView:顶级View


 

 

View的工作流程

View的工作流程主要是指measure、layout、draw这三大流程,即测量、布局、绘制,其中measure确定View的测量宽/高,layout确定View的最终宽/高和四个顶点的位置,而draw则将View绘制到屏幕上。

measure过程

measure过程要分情况来看,如果是一个原始的View,那么通过measure方法就完成了其测量过程,如果是一个ViewGroup,除了完成自己的测量过程外,还会遍历去调用所有子元素的measure方法,各个子元素再递归去执行这个流程。

Layout过程

Layout的作用是ViewGroup用来确定子元素的位置,当ViewGroup的位置被确定后,它在onLayout中会遍历所有的子元素并调用其layout方法,在layout方法中onLayout方法又会被调用。

draw过程

draw过程就比较简单了,它的作用是将View绘制到屏幕上面,View的绘制过程循序以下几步:

  • 绘制View的背景
  • 如果有必要的话,保存这个canvas画布,为该层边缘的fading效果作准备
  • 绘制View的内容
  • 绘制子View
  • 绘制View边缘的渐变褪色效果,类似于阴影效果
  • 绘制View的装饰物


MeasureSpec(测量规格)是什么?有什么作用?

  • MeasureSpec封装了父布局传递给子布局的布局要求,每个MeasureSpec代表了一组宽度和高度的要求 MeasureSpec由size和mode组成。
  • 它有三种模式:

  • MeasureSpec.UNSPECIFIED(未指定(未指定尺寸)),父元素部队自元素施加任何束缚,子元素可以得到任意想要的大小;
  • MeasureSpec.EXACTLY(完全(精确尺寸)),父元素决定自元素的确切大小,子元素将被限定在给定的边界里而忽略它本身大小;
  • .MeasureSpecAT_MOST(至多(最大尺寸)),子元素至多达到指定大小的值。
  •  MeasureSpecs使用了二进制去减少对象的分配。 

 


自定义View/ViewGroup需要注意什么?

  • 让View支持wrap_content
  • 如果有必要 支持padding
  • 尽量不要在view中使用handler 因为view提供了post方法
  • view中有线程或者动画 要及时停止
  • 有嵌套滑动效果时 注意处理滑动冲突


onTouch()、onTouchEvent()和onClick()关系?

  • 首先了解下三者的顺序为:onTouch—–>onTouchEvent—>onclick
  • onTouch方法优先级比onTouchEvent高,会先触发。假如onTouch方法返回false会接着触发onTouchEvent,反之onTouchEvent方法不会被调用。
  • onclick事件的实现等等都基于onTouchEvent,假如onTouch返回true,这些事件将不会被触发。


SurfaceView和View的区别?

  • view在UI线程去更新自己;而SurfaceView则在一个子线程中去更新自己
  • surfaceView是在一个新起的单独线程中可以重新绘制画面,而View必须在UI的主线程中更新画面
  • 在UI的主线程中更新动画,时间一旦太长就会出现问题
  • surfaceView 在新的线程中更新画面所以不会阻塞你的UI主线程,但是涉及到线程同步,需要surfaceView中 thread处理,一般就需要有一个event queue的设计来保存touch event


invalidate()和postInvalidate()的区别?

  • invalidate()用于在主线程中更新UI,postInvalidate()用与在子线程中更新UI,其内部也是使用了handler。

 

Bitmap篇


加载图片的时候需要注意什么?

  • 尽量不要使用setImageBitmap或setImageResource或BitmapFactory.decodeResource来设置一张大图,
  • 因为这些函数在完成decode后,最终都是通过java层的createBitmap来完成的,需要消耗更多内存。
  • 因此,改用先通过BitmapFactory.decodeStream方法,创建出一个bitmap,再将其设为ImageView的 source,
  • decodeStream最大的秘密在于其直接调用JNI>>nativeDecodeAsset()来完成decode,
  • 无需再使用java层的createBitmap,从而节省了java层的空间。


LRU算法的原理?

  • LRU全称是Least Recently Used,即最近最久未使用的意思。
  • LRU算法的设计原则是:如果一个数据在最近一段时间没有被访问到,那么在将来它被访问的可能性也很小。也就是说,当限定的空间已存满数据时,应当把最久没有被访问到的数据淘汰。也是利用了程序的局部性原理。


Android中缓存更新策略?

  • 目前常用的一种缓存算法是Least Recently Used,简称:LRU,LRU是近期最少使用算法,它的核心机制是当缓存控件满时,会优先淘汰那些近期最少使用的缓存对象。采用LRU算法的缓存有:LruCache以及DiskLruCache,LruCache用于实现内存缓存,DiskLruCache用于实现存储设备缓存,因此通过这二者的结合使用,就可以很方便地实现一个高效的ImageLoader。

 

Animation篇


Android中有哪几种类型的动画?

  • Drawable Animation也就是所谓的帧动画,Frame动画。指通过指定每一帧的图片和播放时间,有序的进行播放而形成动画效果。
  • View Animation视图动画(Tween动画,补间动画)。指通过指定View的初始状态、变化时间、方式,通过一系列的算法去进行图形变换,从而形成动画效果,主要有Alpha、Scale、Translate、Rotate四种效果。注意:只是在视图层实现了动画效果,并没有真正改变View的属性。
  • Property Animation属性动画,通过不断的改变View的属性,不断的重绘而形成动画效果。相比于视图动画,View的属性是真正改变了。注意:Android 3.0(API 11)以上才支持。

 


帧动画在使用时需要注意什么?

帧动画使用比较简单,但比较容易引起OOM(或者内存占用过大),因此在使用帧动画时要尽量避免使用过多尺寸过大的图片。


View动画和属性动画的区别?

View动画不能真正改变View的属性,而属性动画可以。


View动画为何不能真正改变View的位置?而属性动画为何可以?

属性动画改变的是对象的属性,比如真正的X,Y坐标属性,而不仅仅是view。


属性动画插值器和估值器的作用?

时间插值器(TimeInterpolator)的作用是根据时间流逝的百分比计算出动画进度的百分比。

类型估值器(TypeEvaluator)的作用是根据属性值改变的百分比计算出改变后的属性值。

 

Drawable等资源篇


了解哪些Drawable?适用场景?

  • ColorDrawable 颜色可绘制类实现简单的单颜色的绘制。
  • BitmapDrawable 位图可绘制类位图可绘制类
  • ClipDrawable 裁剪可绘制类
  • AnimationDrawable 帧动画可绘制类
  • InsetDrawable缩进可绘制类
  • ScaleDrawable 缩放可绘制类
  • RotateDrawable 旋转可绘制类
  • ShapeDrawable 形状可绘制类。
  • PaintDrawable 圆角矩形可绘制类。
  • LayerDrawable 图层可绘制类。
  • TransitionDrawable 淡入淡出可绘制类
  • LevelListDrawable 等级显示可绘制类。
  • StateListDrawable 不同状态下显示可绘制类
  • NinePatchDrawable .9格式的可绘制类
  • GradientDrawable 渐变的可绘制类。
  • PictureDrawable 图像可绘制类。

 

 


mipmap系列中xxxhdpi、xxhdpi、xhdpi、hdpi、mdpi和dpi存在怎样的关系?

xxxhdpi、xxhdpi、xhdpi、hdpi、mdpi对应不同的dpi(像素密度)范围。


dp、dpi、px的区别?

  • 屏幕分辨率:手机在横向、纵向上的像素点数总和,单位:px(pixel),1px=1像素点
  • 屏幕像素密度:每英寸的像素点数,单位:dpi(dots per ich)
  • 密度无关像素:density-independent pixel,叫dp或dip,与终端上的实际物理像素点无关,单位:dp,可以保证在不同屏幕像素密度的设备上显示相同的效果(在Android中,规定以160dpi(即屏幕分辨率为320x480)为基准:1dp=1px,假如同样都是画一条长度是屏幕一半的线,如果使用px作为计量单位,那么在480x800分辨率手机上设置应为240px;在320x480的手机上应设置为160px,二者设置就不同了;如果使用dp为单位,在这两种分辨率下,160dp都显示为屏幕一半的长度)

 


res目录和assets目录的区别?

  •  res会在R.java生成索引ID,在打包的时候判断资源有没有用到,没用到的时候不会被打包进apk中(res/raw文件夹除外),而assets不会。 

  •  res用getResource()访问,assets用AssetsManager访问。 

  • res/raw与assets里的文件在打包的时候都不会被系统二进制编译,都被原封不动打包进APK,通常用来存放游戏资源、脚本、字体文件等。但res/raw不可以创建子文件夹,而assets可以。 

  • res/xml会被编译成二进制文件。res/anim存放动画资源。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
# -*- coding: UTF-8 -*- from lib2to3.pgen2 import driver from appium import webdriver from appium.webdriver.common.appiumby import AppiumBy el1 = driver.find_element(by=AppiumBy.ACCESSIBILITY_ID, value="通讯录") el1.click() el2 = driver.find_element(by=AppiumBy.XPATH, value="/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[1]/android.widget.FrameLayout/android.widget.ListView/android.widget.FrameLayout[3]/android.widget.RelativeLayout") el2.click() el3 = driver.find_element(by=AppiumBy.XPATH, value="/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[2]/android.view.ViewGroup/android.view.ViewGroup/androidx.recyclerview.widget.RecyclerView/android.view.ViewGroup[1]/android.widget.TextView") el3.click() el4 = driver.find_element(by=AppiumBy.XPATH, value="/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[2]/android.view.ViewGroup/android.view.ViewGroup/androidx.recyclerview.widget.RecyclerView/android.view.ViewGroup[8]") el4.click() el5 = driver.find_element(by=AppiumBy.XPATH, value="/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.widget.FrameLayout[2]/android.view.ViewGroup/android.view.ViewGroup/androidx.recyclerview.widget.RecyclerView/android.view.ViewGroup[11]") el5.click()
最新发布
06-08

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值