美文网首页
Android基础梳理

Android基础梳理

作者: LeoFranz | 来源:发表于2019-08-05 14:21 被阅读0次

安卓项目结构

gradle依赖包括 本地依赖 远程依赖 库依赖

三个sdk配置

  • minsdk 表示最低兼容系统版本,低于此版本将不能被安装,不过应用在低版本上仍然可能出现兼容性问题
  • targetsdk 表示该应用为哪个api级别设计的,在此版本上会运用该版本api所有的新特性,在更高版本上,也可以正常运行,但其版本的的新变化将会被忽略
  • SDK编译版本,是指用哪个版本的SDK编译软件,会引用指定版本的类和方法——前两个配置项会通知给操作系统,但这项仅仅和编译相关

可能的兼容问题:

  • 用高版本SDK编过的apk,在低版本设备上运行可能会崩溃,因为低版本不支持一些高版本出现的功能,建议用Android Lint提前检查——编过不代表运行正常——解决方案建议在代码中使用Build.VERSION.SDK_INT(代表安卓设备版本号)进行版本检查,不同版本代码实现方式不一样。
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODE.LOLLIPOP) { //do something } else { //do something }

build.gradle文件的作用是覆盖和设置Manifest文件

兼容库
貌似是用于兼容不同版本的差异

  • Android 文档可以脱机查看,在SDK安装目录的dos目录下面。
  • 通过api过滤功能可以查看同一个类的版本差异

Activity

intent filter
data中标签相同活动就能相应

构建项目注意点
  • Android studio 中R文件不会根据资源修改而实时跟新,每个项目有一个代码编译用的R隐藏文件,编辑区可见的R.java仅在应用打包安装时更新。
  • 代码补全功能
    快捷键
    找资源id:fbc或.cast
    命名常量const,key
    打log logd
    循环 fori foreach
    判断 ifn inn
    设置可见性 gone
    switch判断 .switch
    后缀型快捷键,为.**
  • aapt(Android Asset Packaging Tool)将文件资源压缩后打包到apk中
  • 在setContentView方法中,activity的LayoutInflater会实例化布局文件中的每一个view对象,当然可以在代码中创建视图,但这不符合视图和逻辑分离的原则。
  • Androidstudio 已经整合了编译过程,如果需要脱离IDE编译apk,简单方法是采用命令行工具,目前推荐gradle工具。在命令行中,切换到项目目录并执行以下命令:
    ./gradlew tasks for mac
    gradlew.bat tasks for windows
    会看到一系列可用任务,如果任务时installDebug(安装但不运行),可以再执行以下任务
    ./gradlew installDebug
    gradlew.bat installDebug
  • 复制项目,仅需要找到项目根目录,复制整个文件,重命名,再从studio中导入即可。
Activity的生命周期

交互周期 onResume - onPause
可见周期 onStart - onStop
生命周期 onCreate - onDestroy

  • 这类方法不能被主动调用,其重写必须先默认实现超类方法。

关于保存activity中的数据

  • 停止的activity不保证能存活多久,系统随时可能回收;
  • 暂停状态的activity出现场景一般为其上启动了一个透明背景activity或者小于屏幕尺寸的activity(如多窗口模式)
  • 基于用户体验考虑,系统不会回收可见的(未执行stop方法的activity);
  • 设备旋转时会销毁当前activity,并发生运行时资源配置(runtime configuration change),这时候建议为新的activity准备横屏的layout,将目录改为layout-land,并将screen orientation属性中选中Landscape. 横屏的layout建议用FrameLayout包装,它不管子视图的位置,其只取决于他们各自的layout_gravity。

处理方案

  • onSaveInstanceState()方法在stop方法前一定会由系统调用,除非是按back键(主动退出,没有保存数据的需要)和重启系统,还有其他场景???数据可以保存在该活动的bundle中,bundle中保存对象不是好的主意,因为该对象重新获取时可能已经无用;
  • activity实例被销毁后,如果需要保存对象记录数据,该activity就会进入暂存状态,再次创建实例时就会调出这些对象记录。这就是OnSaveInstanceState()方法可行的基础。
  • 建议在onstop中保存永久性数据,在bundle中保存当前小数据。
  • Android保存数据现状
    至少在Android7.X时期,系统低内存时还做不到销毁单个activity,会直接清除整个应用进程。
    正如之前所述,理论上系统不会杀死有可见activity的进程。
    在开发者选项中,打开Don't keeps activities 表示当用户停止当前activity时,系统会直接回收activity,这里可以测试onSaveInstaceState()方法的有效性。

Activity的新建流程

  • 启动activity的时候,intent其实是先传递到ActivityManager,然后转发到目标activity
  • 如果activity是通过startActivityForResult()启动的,代码总会返回给父activity,如果用户没有调用setResult,父activity就会收到Activity.RESULT_CANCLD结果代码。
  • ???activityManager维护着一个所有APP的共享回退栈,即所有app界面按返回键都会回到桌面,这也是将activityManager设计成操作系统级活动管理器的原因之一。

广播

标准广播&有序广播
标准广播无序,几乎能让所有程序差不多同时接受;有序广播会让程序按一定顺序接受,同一时刻只有一个接受者,可以调整广播接受者的优先级,并且可以被拦截。
本地广播只能在程序拉起时候,在同一个APP中发送和接受,对于数据安全性比较有好处。
动态广播需要及时反注册,不需要在xml文件中配置;静态广播的运行不依赖程序启动,exported属性表示该广播接收器是否接受本程序以外的广播,enabled表示是否启用这个广播接收器。

广播不会开启新的线程,所以不能做太耗时的操作。

内容提供器

运行时权限,需要提前声明并且动态获取,用户主动关闭
contentResover: 不同于sqlite的表名路径,以URI为参数,包括包名和路径
getType方法的作用:根据传入的URI返回按规范编写的自定义的MIME类型字符串,这样系统能不用再分析Cursor,便可快速识别是要返回单条数据还是多行数据,能提升系统性能。
URI里有包名和表名,能够精确定位访问路径
contentObserver需要注册与反注册
一般需要配合handler使用。

权限都需要提前声明,在6.0之前权限必须一次性申请完毕,后来加入了运行时权限,用户可以随时在设置中关闭已经授予的权限
contentResolver,uri包括authority和path,
contentProvider会在onCreate中完成对数据库的创建和升级,返回true表示创建成功,当ContentResolver尝试访问程序中的数据时候,内容提供器才会被初始化。
getType中的MIME类型告诉系统不需要解析cursor来辨别是改变一条数据还是多条,一定程度上提高性能

多媒体

通知

通知可以再不同组件创建,建议使用兼容库中的通知NotificationCompat用于build通知,
pendingIntent生成时有四个参数getActivity(android.content.Context, int, android.content.Intent, int)最后参数确定pendingIntent行为:
FLAG_ONE_SHOT 一次性使用
FLAG_NO_CREATE pendingIntent不存在就返回空
FLAG_CANCEL_CURRENT pendingIntent已经存在就取消现有pendingIntent,创建一个新的
FLAG_UPDATE_CURRENT pendingIntent已经存在就保留,并以新的intent覆盖现有的pendingIntent中的intent
Scancel方式,seAutoCancel(boolean auto)或者显式调用NotificationManager.cancel(int id);来取消
可以设置通知声音、震动、LED灯,也可以设置默认效果setDefault();
setStyle,包括:NotificationCompat.BigTextStyle用于设置大文本,NotificationCompat.BigPictureStyle.bigPicture()传入一个Bitmap,
setPriority设置通知的优先级,有5个常量值

相机

调用相机接口,首先构建一个存储所拍摄图片的contentProvider,然后将Uri绑定一个新图片对象作为intent中的参数,启动一个activity,在onActivityResult中通过ContentResolver来查询相片地址,使用BitmapFactory.decodeStream方法将图片生成为一个bitmap对象,放置到imageview当中。
获取相册内容,通过intent启动一个activity,在onActivityResult中获取返回的uri,解析uri,通过该uri查询特定相片地址后返回String类型的相片地址,然后通过BitmapFactory.decodeFile(String imagePath)来将相片转换成bitmap,照片一般需要压缩后再加载。

播放音视频

使用MediaPlayer和VideoView,后者其实是封装了MediaPlayer,注意VideoView在视频格式的支持率和播放效率方面有较大不足。

持久化技术

文件存储

最简单,使用context类中的openfileoutput openfileInput 结合javaIO流存取数据,保存在。。。文件中。不对文件进行任何格式化处理,文件会被原封不动地存取,适合保存小型二进制文件和文本文件。有两种模式,private和append,对于前者,当保存同名文件时会替换之前的文件;对于后者,则是会在同名文件上追加内容。

sharedPreference

以键值对形式存储数据,数据能以原有格式存取,保存在。。。文件中。只有一种模式private可选,使用时有两种SharedPreference对象可选,一是context类下的sharedPreference,传入两个参数;二是activity中的。。。,保存的文件以activity类名为文件名。sharedPreference实质上以xml文件格式保存数据

sharedPreference中apply和commit方法区别

  1. apply没有返回值而commit返回boolean表明修改是否提交成功
  2. apply是将修改数据原子提交到内存, 而后异步真正提交到硬件磁盘, 而commit是同步的提交到硬件磁盘,因此,在多个并发的提交commit的时候,他们会等待正在处理的commit保存到磁盘后在操作,从而降低了效率。而apply只是原子的提交到内容,后面有调用apply的函数的将会直接覆盖前面的内存数据,这样从一定程度上提高了很多效率。
  3. apply方法不会提示任何失败的提示。
    由于在一个进程中,sharedPreference是单实例,一般不会出现并发冲突,如果对提交的结果不关心的话,建议使用apply,当然需要确保提交成功且有后续操作的话,还是需要用commit的。
Sqlite数据库

占用内存小,不需要登录,
onCreate创建
onUpgrade升级
创建数据库通过SQliteOpenHelper类的实例化,然后通过getReadableDatebase和getWritableDatabase方法返回可操作数据库的对象,升级时需要对SQliteOpenHeliper的构造方法中最后一个参数加一。可以使用纯SQL语法操作数据库。

网络技术

WebView

调用系统内核实现内嵌浏览器功能,封装了http请求和解析的功能。

HttpURLConnection
HttpURLConnection connection = new URL("http://www.github.com").openConnection();

可通过BufferReader对数据进行解析。一般我们通过子线程中开启链接获取数据,再通过RunOnUIThread方式切换到主线程中处理。

OKHttp
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url("http://www.baidu.com").build();
Response response = client.newCall(request).execute();
String responseData = response.body.string();
//do something with data;
解析网络数据
  • 解析xml
    Pull方式,使用XMLPullParser
    SAX方式,继承DefaultHandler
  • 解析Json
    使用JSONObject
    使用GSON

服务

handler机制
AsyncTask
两种启动服务的模式区别,BIND_AUTO_CREATE 会让onStartCommand不执行
开发者选项中可以将服务找到
前台服务 通过startForeground方法把服务变成前台服务
IntentService自动继承开启线程,自动终结服务的方式,核心方法是onHandleIntent

LBS服务

  • 网络定位 利用附近基站定位,室内外皆可使用,精度一般
  • GPS定位 利用手机内置GPS硬件直接和卫星交互获取定位信息,仅室外可用,精度高
    使用百度定位SDK:
    更新位置显示,选择定位模式,使用mapView将地图显示,将自己显示在地图上

Material Design

顶部导航栏、滑动菜单、悬浮按钮、undo按钮、卡片式布局、下拉刷新、可折叠式标题栏
来源自DesignSupport库、support-v4库、cppcompat-v7库等

其他高级技巧

serialize和parcelable的区别,将对象完全序列化和将对象拆解,每部分拆解成intent所支持的数据类型,ParceLable效率较高

AlarmManager启动一个定时任务
AlarmManager是一个系统服务,在指定时间后通过pendingIntent启动一个服务或者广播接收器,Android对系统服务有限制,以限制CPU被唤醒次数,控制功耗为理由,对触发时间相近的Alarm任务进行集中处理

Doze模式
设备屏幕关闭处于静息状态一段时间后,会间歇性睡眠,一定时间后唤醒处理数据同步,alarm任务等操作。

多窗口模式
进入该模式activity会重建,该模式下生命周期与单窗口模式略有不同,禁止activity重建可以通过manifest中android:configChanges配置,并重写onConfigurationChange方法。
通过在application或者activity标签中添加android:resizeableActivity属性允许/禁用多窗口模式(api24及以上时候可用),如果设备api低于24,需要额外加上android:screenOrientation属性禁止设备屏幕旋转。

相关文章

网友评论

      本文标题:Android基础梳理

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