此文章是根据B站的视频教程整理总结的笔记,用白话说明一些Android开发的入门知识,共勉。
B站教程链接:https://www.bilibili/video/BV13y4y1E7pF?p=12&spm_id_from=pageDriver
视频是基于Java的,我用Kotlin写的源码链接(Topics = "android-bilibili-course"):https://github/Flameyjh?tab=repositories
目录
控件介绍
TextView
Button
EditText
ImageView
ProgressBar
Notification
ToolBar
AlertDialog
PopupWindow
布局
LinearLayout
RelativeLayout
FrameLayout
TableLayout
GridLayout
ConstraintLayout
ListView
RecyclerView
动画
帧动画
补间动画
属性动画
单位和尺寸
ViewPager
Fragment
ViewPager2
Viewpager2+Fragment实现微信首页
Activity
Service
Receiver
热修复
在项目中使用高德地图
引入高德地图SDK
在项目中显示地图
地图关键字搜索与定位
Glide
OkHttp
Retrofit
GSON
使用Gson完成序列化和反序列化
变量值为NULL时的序列化和反序列化
控制序列化/反序列化的变量名称
控制是否参与序列化/反序列化
RX(ReactiveX)
RX思维下载图片
RX思维的魅力
自定义observer
数据存储
类似“记住用户名”打勾,看书到69页,这种配置信息应该保存到SP中。SQLite和ROOM都是数据库,SQLite是早期原生数据库,ROOM是后期简洁数据库,类似电话簿这种列表信息应该保存到数据库中。
SP
SQLite
ROOM
Intent
Android 多媒体
组件化
项目发布
控件介绍
TextView
Button
EditText
输入框里面的内容。继承自TextView,可以设置图片drawable、默认输入提示hint等。
ImageView
图片。
ProgressBar
进度条。
Notification
通知。
ToolBar
页面上方导航栏。可以设置背景、标题、图标等。可以在内部添加TextView使文字居中。
AlertDialog
弹出来的对话框。需要new一个构建器AlertDialog.Builder去设置对话框的内容。可以添加“确认”、“取消”、“中间”等不同类型的按钮。
setView(name_view) 方法可以给对话框添加View,xml布局可以变成View去使用:View view = getLayoutInflater().inflate(R.layout.name_xml, null)。
PopupWindow
弹出来的对话框。直接new一个PopupWindow即可。可以设置点击空白处取消或者点击按钮取消。
布局
LinearLayout
线性布局。oritation设置水平、垂直。gravity在父容器中设置,设置子元素整体居中、水平方向居中、垂直方向居中。layout_gravity在子元素中设置,设置它在父容器中的对齐方式。layout_weight设置剩余空间根据权重分配。
RelativeLayout
相对布局。默认放在父容器左上角。根据父容器定位layout_alignParentLeft。根据兄弟组件定位layout_toLeftOf。设置组件与父容器的间距margin。设置组件内部元素的间距padding。
FrameLayout
帧布局。设置前景,设置前景位置。
TableLayout
表格布局。和TableRow结合使用,可以一行一行的显示。设置需要被隐藏的列。设置允许被拉伸、收缩的列。子控件显示在第几列、横向跨几列。
GridLayout
TableLayout不能把两行合并,只能把两列合并。GridLayout既能行合并,也能列合并。
ConstraintLayout
约束布局。约束上下左右。可以通过design界面的拖拽实现约束。可以添加指导线进行更方便的设置。可以直接推导约束。
ListView
- 创建一个ListView的布局,创建一个item的布局;
- 创建一个List类型的数据,表示每个item的文本内容;
- 创建一个继承自BaseAdapter的Adapter,重写getView方法,拿到item布局渲染的convertView,把数据绑定到每一个convertView。
- 可以用ViewHolder优化,把item的view元素放到viewHolder里,通过viewHolder去设置和取用这些元素。
RecyclerView
动画
帧动画
通过多张图片替换形成动画。
- 设置animation-list类型的xml,作为其他布局的background使用;
- 通过布局.getBackground得到AnimationDrawable类型anim。然后通过anim.start()启动动画。
补间动画
通过调整透明度、旋转、缩放、平移形成动画。
- 通过加载xml动画设置文件来创建一个Animation对象。Animation animation = AnimationUtils.loadAnimation(context, R.anim.动画设置文件名);
- 普通的图片就可以通过开启animation来设置动画。imageView.startAnimation(animation)。
属性动画
ValueAnimator改变值, ObjectAnimator改变对象的属性值。
单位和尺寸
px:像素。绝对单位,默认单位。pt:绝对单位。dp:相对单位。xml中常用,不同设备不同显示效果。sp:相对单位。和dp可以转换,主要用于字体显示。
ViewPager
能够左右滑动的资源位。
- 3个子页面的xml布局文件,一个包含ViewPager的xml文件;
- 在Activity中把三个子页面的布局渲染成3个view,并添加到一个ArrayList中去,作为数据;
- 自定义一个继承自PagerAdapter的myAdapter,在里面绑定数据;
- 把viewPager的adapter设置为myAdapter。
Fragment
可以看做小型简单的activity。用于平板电脑界面动态灵活设计,一个布局适配两种设备,简单高效,易于维护。
为什么用fragment而不用两个layout达到效果?两个layout需要判断当前屏幕大小然后转换布局。
特性:具备生命周期,不能独立使用,必须委托在activity中才能运行。一个activity可以有多个fragment,一个fragment也可以在多个activity中重复使用。
使用方法:
- 创建一个fragment,就会出现一个Fragment.java和一个对应的fragment.xml;
- 在Fragment.java里,把fragment.xml渲染成view,并且给view里面的元素添加监听;
- 在其他页面的布局文件,比如main.xml 中去使用上面创建的fragment.java。
fragment动态添加和管理:
使用fragmentManager,fragmentTransaction。
Activity和Fragment通信:
- 原生方案:Bundle。fragment.setArguments(bundle)。
- 类与类通信常用方案:接口作为参数类型传值。具体操作:在F里面new一个空的接口类型的对象作为函数参数,提供一个set函数给外部;然后在B中调用A的set函数,new一个有内容的接口对象赋值给A中空的接口对象(这一步其实就是对接口里面函数的具体实现)。
- 上面两种方案需要信息已经提前准备好,但是我们还需要能够即时的通信。其他封装好的方案:eventBus、liveData。这些都是观察者模式。
Fragment生命周期:
activity的onCreate对应fragment的:onttach:和activity联系,onCreate:解析bindle,onCreateView:解析xml,onActivityCreated:表示activity已经创建。
activity的onDestroyed对应fragment的:onDestroyView,onDestroy,onDetach。
ViewPager2
可以实现横向页面切换,比如微信首页。ViewPager2继承自ViewGroup,实际对recyclerView进行了封装。
怎么用:
- 自定义类ViewPagerAdapter继承自Recyclerview.Adapter;
- 自定义类ViewPagerAdapterViewHolder继承自Recyclerview.ViewHolder。
Viewpager2+Fragment实现微信首页
- 一个ViewPager2+多个Fragment:在activity的xml文件中创建一个ViewPager2控件,把多个Fragment添加到List作为参数传给ViewPager2的Adapter。(viewPager.setAdapter)
- 新建底部导航栏,通过对ViewPager2的滑动监听把上面的Fragment页面切换和下面的导航栏切换联系来。(viewPager.registerOnPageChangeCallback)。通过给下面的导航栏的四个按钮添加点击事件把下面的点击和上面的切换联系起来。
Activity
继承自AppCompatActivity。
Activity跳转:
- 新建一个Activity类继承自AppCompatActivity,设置它的布局,组件必须在AndroidManifest.xml清单文件中注册。
- 利用Intent跳转。startActivity(new Intent(this, MainActivity2.class))。
Activity生命周期:
onCreate()布局和控件的初始化。onStart()做标签的改变。
Service
服务在后台默默运行,不可见。比如上传下载,服务器更新,音乐播放。组件必须在AndroidManifest.xml清单文件中注册。
startService与生命周期:activity销毁后仍然运行。
bindService与生命周期:activity销毁后自动解绑服务。它的实现需要创建activity和service的桥梁。
Receiver
广播。分为系统广播和用户自定义广播。比如网络连接与断开,蓝牙连接与断开的广播。组件必须在AndroidManifest.xml清单文件中注册。
静态注册接收广播:
- 定义广播接收者.java,设置action标签与之后发送的标签保持一致;并在AndroidManifest清单文件注册这个接收者。
- 在activity中可以发送广播。(intent.setAction(ActionUtils.ACTION_FLAG); sendBroadCast(intent))。
动态注册接收广播:
- 定义广播接收者.java,设置action标签与之后发送的标签保持一致;并在activity中注册这个接收者;把清单文件的工作放到了Java文件中。
- 在activity中可以发送广播。
热修复
应用上线后出现bug,可以把补丁包发布到服务器上,用户只需要使用补丁包修复bug。
工具:Tinker、Bugly(提供补丁管理服务)。
在项目中使用高德地图
引入高德地图SDK
- 引入SDK依赖。官网下载所需的aar包——粘贴到app的libs文件中——app的build.gradle中配置。
- 配置权限,高德key等等。到这里配置完成,可以用了。
- 在xml文件中加入MapView,然后在activity.java 代码中获取地图控件引用。(MapView mapView = findViewById(R.id.map),后续写代码操作地图)
在项目中显示地图
地图关键字搜索与定位
Glide
Android图片加载库,帮助完成图片加载和展示。可以自动加载apk中的资源,以及手机中的图片资源,以及网络中的资源。GitHub中有简体中文文档。
可以选择把图片资源与fragment或者activity的生命周期绑定,从而减少图片资源OOM的可能。
Glide基础使用:图片占位符、错误符、后备回调符。
- 需要在Manifest清单文件中加入网络权限和SD卡读写权限。
- new一个RequestOptions。通过.placeholder(R.Drawable.XX).error().fallback().override(width,height)等设置各种占位符;
- 在Glide中应用requestOptions。通过Glide.wirh().load().apply(requestOptions).transition().transform(new Rotate(90)).into(imageView)。自定义旋转效果可以写一个类继承自BitmapTransformation。
Glide进阶:加载动画与请求加载配置、圆角变换。
Glide高级用法Generated API:
- 在dependencies引入Glide依赖;
- 在Application模块中包含一个AppGlideModule的实现;
- 此时能够更简单地完成占位符等配置。GlideApp.with()..load().placeholder().into(imageview)
代码资源:kotlin中使用Glide:https://codeantenna/a/dKBtgi8k6r
OkHttp
- new一个OkHttpClient对象;【需要一个代理】
- new一个Request对象;【创建一个请求】
- new一个Call对象。call.excute调用同步请求(sync),call.enqueue调用异步请求(Async)。【代理把请求创建成一个call并发出去】
Http教程(比如上传不同类型的数据对应的格式):https://www.runoob/http/http-content-type.html
拦截器:完成一些发送请求时的统一处理。
缓存:发起一次请求后,后续还要进行同样的请求。如果符合缓存规则,则直接从本地读取。默认情况okhttp的缓存时关闭状态。
cookie:为了辨别用户身份,进行会话跟踪而存储在本地的数据。
Retrofit
封装了OkHttp,比OKHttp更简单。
好用工具:
- google扩展程序Talend API Tester,在线发送请求查看返回结果;
- 在线JSON校验格式化工具(Be JSON), 在线将json数据转换为Java类;
- 玩Android 开放API-玩Android - wanandroid, 公开域名,返回上传数据用于测试。
Retrofit的基本使用:
- 根据Http接口创建网络接口;
- 创建Retrofit对象,并生成网络接口的实现类对象;
- 接口实现类对象调用对应方法获得响应。
Retrofit中的注解:
方法注解、标记注解、参数注解。
Retrofit中的转换器:
接到服务器的响应一般是String类型的字符串,实际开发中需要对字符串进行解析使其变成一个Java Bean对象。比如:服务器响应格式为Json格式字符串,就可以利用GSON库完成反序列化的操作,把Json对象转为Java类对象。
而Retrofit提供了多个转换器使得响应能够完成自动的数据转换。(.addConverterFactory(GsonConverterFactory.create()))
Retrofit中的嵌套请求与适配器:
嵌套请求:需要先请求接口A再请求接口B,比如需要先登录拿到Cookie才能请求收藏文章列表。这个时候需要在onResponse方法里面嵌套才能实现。
Retrofit的适配器:Retrofit的接口方法返回类型必须是Call,如果能够将Call改为RxJava中的Observable,对于嵌套的情况,就能得到非常方便优雅地解决。这就是适配器的功能。
文件的上传与下载:
上传:post方法。使用@Multipart和@Part注解。
下载:get方法。使用输入输出流将返回的文件写入。(InputStream和FileOutputStream)
另外使用@Streaming注解能够防止内存溢出。
GSON
使用Gson完成序列化和反序列化
Java Object 序列化/反序列化、Array和List的序列化/反序列化、Map和Set的序列化/反序列化。
- 普通对象Object和数组类型对象Array都可以使用toJson, fromJson 完成序列化和反序列化。
- 对于List对象、Map对象,Set对象,他们包含泛型,比如List<User>, Map<String, User>, Set<User>。序列化还是用toJson,但是反序列化需要用到TypeToken先得到Type对象,再用fromJson。
变量值为NULL时的序列化和反序列化
- 一个对象的属性为NULL时,GSON默认处理是忽略这个字段。
- 一个集合中存储的数据为NULL时,GSON默认处理是不会忽略,保存一个null。
控制序列化/反序列化的变量名称
如果希望JSON字符串字段名不以变量名作为key,比如JSON字符串中的key与Java中的关键字重复时("class":"1"),可以借助@SerializedName注解控制JSON字段中key的命名。
控制是否参与序列化/反序列化
serialize是否参与序列化,deserialize是否参与反序列化。@Expose(serialize=false, deserialize=false);。
使用此注解需要改变GSON对象的创建。GSON gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create()。
RX(ReactiveX)
响应式编程思维:根据上一层的响应 来 影响下一层的变化。其实就是观察者设计模式。
RX思维下载图片
如果采用传统方式完成图片加载,每位开发者的思想都不一样。比如:A同学采用线程池,B同学采用new Thread + Handler,C同学采用古老的方式。这样后面开发者接收就很痛苦。
步骤:用户点击——1. 正在加载的加载框——2. 把String类型的网址分发出去——3. 把String变换成Bitmap——4. 显示图片——5.隐藏加载框。
RX思维的魅力
有一个需求001:图片加载需求,现在加一个需求002:给图片加水印。只需要添加中间层即可。
RX思维总结:流式链条:起点——需求1——需求2——终点。
自定义observer
服务端返回客户端:
JSON——Java实体bean。总bean包括data, code, message。(其中的data成功时是成功bean,失败时可能是null或0)
实战需求:如果登陆成功,只想拿到成功bean;如果登陆失败,只想拿到message。
数据存储
类似“记住用户名”打勾,看书到69页,这种配置信息应该保存到SP中。SQLite和ROOM都是数据库,SQLite是早期原生数据库,ROOM是后期简洁数据库,类似电话簿这种列表信息应该保存到数据库中。
SP
sharedpreference, 首选项。首选项不能存在太多的信息,因为当程序运行首选项里面的信息会全部加载进内容。(SP xml 格式 map(key--value))
SharedPreferences sp = getSharedPreferences("name", Context.MODE_PRIVATE); //当前模式是覆盖,MODE_APPEND是添加。
保存数据:sp.edit().putString("key", "value").apply(); //apply才会写道xml配置文件里去。
获取数据:sp.getString("key", "默认值"); //默认值是key获取不到时获取到的。
实战需求:记住用户名密码的登陆需求。要考虑初始化,考虑第二次登陆要回显数据。
SQLite
关系型数据库,嵌入式的数据库,体积小,计算器,手表等嵌入式设备上。原来需要安装一个数据库软件,Android里面的数据库是由底层的sqlite.c的代码来动态生成的。
SQLite可视化工具:SQLite Expert Personal 3
SQLite创建库创建表、增删改查操作:
- 创建自己的MySQLiteOpenHelper工具类,它继承自提供的抽象类;
- 在这个工具类里面用SQL语句创建表;
- 利用helper实例得到数据库和表。
ROOM
对SQLite的封装,流畅易用的访问数据库。以前需要帮助类、SQL语句、执行SQL语句、创建表等,非常繁琐。ROOM直接通过注解就可以实现,用户只需要拿到DAO就可以对数据库增删改查。
ROOM三角色:
@Entity:一个类完成Entity的注解就是一张表。(普通类)
@Dao:一个类完成DAO的注解就可以对上面的表进行增删改查。(接口)
@Datebase:一个类完成DB的注解就可以进行数据相关的存储和创建,在这里关联之前的表 数据库信息。(抽象类)
Intent
activity1通过intent跳转到activity2,过程中intent可以携带数据。
Intent传递基本数据类型:可以在activity1中通过intent.putExtra携带数据,在activity2中通过intent.getStringExtra拿到数据。
Intent传递Bundle:在activity1中把数据包装成Bundle对象,在activity2中自动拆除包装。
Intent传递Serializable:在activity1中把数据放在一个类中,并使这个类继承Serializable接口。
Intent传递Parcelable:在activity1中把数据放在一个类中,并使这个类继承Parcelable接口。不过这个方法要麻烦一些。
选择:JVM平台 Java开发 选择Serializable,Android 优先使用Parcelable,因为Parcelable支持 兼容 安卓虚拟机,比Serializable性能高很多。
Android 多媒体
MediaRecorder录制视频:
MediaPlayer播放视频:
VideoView播放视频:相当于封装了MediaPlayer,提供了进度条、暂停、继续、上一条、下一条等功能。但是这些UI不能自己改,如需自定义还是要用MediaPlayer。
SoundPool播放音效:1. 创建;2. load;3. play;4. unload; 5. release。(特别是一些短暂的音效)
组件化
组件化和模块化的区别:
组件化的重心主要是放在业务逻辑层,主要是为了拆分业务逻辑,只针对业务逻辑。
模块化的重心主要是为了功能的重用,按功能拆分一个个的插件,针对整个项目。
组件化和插件化的区别:
组件化不管把业务拆分成多少个模块,最后在打包上线的时候都会生成一个apk。
插件化也是拆分为很多个插件模块,但是在最终打包之后,成为了很多apk。我们把它上传到服务器上,用户使用的时候,只需要下载相应的apk即可,然后使用动态加载技术,加载里面相应的activity。
组件化开发的优势:
- 我们每次运行不需要整个项目运行,而是运行单一的组件即可;
- 如果我们要将某一个模块用到新项目中去,就很简单了,因为每一个独立的模块都是一个application。因为application是不能依赖其他application的,我们就不需要解耦合了、资源等等。
项目发布
1. 生成release apk;2. 生成签名;3. 加固;4. 设置多渠道。(可以使用360加固助手)
更多推荐
Android(安卓)开发零基础入门课程【笔记】
发布评论