实习笔记-16

Android View绘制流程

performTraversals()

获取Surface对象,performMeasure-丈量View树的各个view的大小,performLayout-对整个视图树进行布局,performDraw,对视图树进行绘制
源码解析

  1. 第一阶段,确定activity的宽高
1
2
3
4
5
6
7
8
9
if(Activity窗口是第一次被请求执行测量、布局和绘制操作){
if(如果窗口的类型是有状态栏的){
Activity窗口所需要的宽度和高度就是除了状态栏;
}else{
Activity窗口所需要的宽度和高度就是整个屏幕的宽高;
}
}else{
Activity窗口的宽高为frame成员变量中的保存的上一次测量、布局和绘制时的值;
}
阅读更多

实习笔记-15

gradle全局配置

配置GRADLE_USER_HOME环境变量

实习笔记-14

更新桌面小组件

  1. Handler更新:只能坚持几秒钟
  2. Service发送广播更新
    1. Service的context从onReceive获取,一切正常。会存在保活的问题,至少30分钟系统才调用onUpdate一次
    2. 使用lateinit保存onUpdate的context,会报错lateinit property mContext has not been initialized
  3. onUpdate暴力递归 点击后无法更新

实习笔记-25

创建型

单例

优点

  • 节省资源
    • 内存
    • 重对象中包含的io,文件指针
  • 调用方便

缺点

  • 适用于昂贵对象,对于轻量对象,为了维护单例造成的同步等开销比创建一个对象更高。得不偿失
  • 不方便mock,(可以把单例对象作为函数参数则可以mock),相较于静态方法更方便(静态方法需要代理的方式mock)
  • 测试时常常并行测试,使用单例会降低效率
    函数式编程,拷贝
    云控,打点 Alex
    静态工具方法,少用,不要有状态,确保永远不会变
阅读更多

实习笔记-24

设备到设备文件传输

如果您的应用以 Android 11 或更高版本为目标平台,您将无法使用 allowBackup 属性停用应用文件的设备到设备迁移。系统会自动启用此功能。

不过,即使您的应用以 Android 11 或更高版本为目标平台,您也可以通过将 allowBackup 属性设为 false 来停用应用文件的云端备份和恢复。

非 SDK 接口限制

相机

媒体 intent 操作需要系统默认相机
从 Android 11 开始,只有预装的系统相机应用可以响应以下 intent 操作:

阅读更多

Kotlin学习笔记——GridView

Kotlin学习笔记——GridView

1
#define 小毛驴 xml

使用方法

  1. 设计好界面
  2. 新建一个小毛驴文件,这个小毛驴文件是GridView中,每一个Item的界面布局文件
  3. (可选)编写一个数据类,用来保存每个item中的数据,用data class可以很方便
  4. 编写一个继承BaseAdapter适配器的类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class GridAdapter(private val context: Context, private val strList:MutableList<myItems>, private val background:Int) : BaseAdapter() {
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
var view = convertView
val holder:ViewHolder
if (convertView == null) {
view = LayoutInflater.from(context).inflate(R.layout.item, null)
//我猜这个函数的作用是指定这个类所对应的小毛驴文件
holder = ViewHolder()
holder.myLayout = view.findViewById<LinearLayout>(R.id.all)
holder.desc = view.findViewById<TextView>(R.id.textView)
holder.pic = view.findViewById<ImageView>(R.id.imageView)
view.tag = holder
} else {
holder = (view?.tag) as ViewHolder
}
//以上是固定格式
val myItem = strList[position]
//传进来的数据数组,适配器根据数组大小反复调用这个函数构造ViewList
//position是当前位置,对应数组下标
//holder.myLayout.setBackgroundColor(background)
holder.desc.text = myItem.desc
holder.pic.setImageResource(myItem.image)
//以上是自定义每个控件的显示内容
return view!!
}

override fun getItem(position: Int): Any = strList[position]
override fun getItemId(position: Int): Long = position.toLong()
override fun getCount(): Int = strList.size

inner class ViewHolder {
lateinit var myLayout:LinearLayout
lateinit var desc: TextView
lateinit var pic: ImageView
}
}
  1. 如果编写了数据类(起了一个c++结构体的作用,因为数组只能传递一个),创建对应的List并且赋值
  2. 给GridView添加适配器
阅读更多

Kotlin学习笔记——EditText

输入监听器

方便起见,在activity的内部写一个内部类,用来监听输入

编写监听器

1
2
3
4
5
6
7
8
9
10
11
inner class EditWatcher : TextWatcher {
override fun afterTextChanged(s:Editable) {

}
override fun beforeTextChanged(s:CharSequence, start:Int, count:Int, after:Int) {

}
override fun onTextChanged(s:CharSequence, start:Int, count:Int, after:Int) {

}
}

注意

  1. 把Editable直接toString()就是用户当前的输入
阅读更多

Kotlin学习笔记——Fragment

1
#define 小毛驴 xml

使用方法

Fragment与ViewPager搭配,实现翻页,实现每页多个控件

  1. 写好每个item的小毛驴文件和数据传送类
  2. 继承Fragment类,自定义一个fragment
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class BlankFragment : Fragment() {
var ctx:Context? = null
var mPosition:Int = 0
var mInageId:Int = 0
var mDesc:String = ""
var title:String = ""

val colorNames = listOf<String>("红色","黄色","绿色","青色","蓝色")
val colors = intArrayOf(Color.RED, Color.YELLOW, Color.GREEN, Color.CYAN, Color.BLUE)
var mSeq:Int = 0
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
ctx = activity
if (arguments != null) {
mPosition = arguments!!.getInt("position", 0)
mInageId = arguments!!.getInt("image_id", 0)
mDesc = arguments!!.getString("desc")
title = arguments!!.getString("title")
}//获取数据
val view = inflater.inflate(R.layout.show_info, container, false)

view.findViewById<ImageView>(R.id.imageView).setImageResource(mInageId)
view.findViewById<TextView>(R.id.textView).text = mDesc
//显示数据
return view
}

companion object {
fun newInstance(position:Int, image_id:Int, desc:String, title:String) : BlankFragment {//调用这个函数,创建新的fragment

val fragment = BlankFragment()
val bundle = Bundle()
bundle.putInt("position", position)
bundle.putInt("image_id", image_id)
bundle.putString("desc", desc)
bundle.putString("title", title)
fragment.arguments = bundle
return fragment
}
}
}
  1. ViewPager的适配器
阅读更多

Kotlin学习笔记——BroadCast

1
#define 小毛驴 xml

收发广播

使用场景:Fragment想要向外传递信息

  1. 在Fragment中发送广播
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class BlankFragment : Fragment() {
var ctx:Context? = null
var mPosition:Int = 0
var mInageId:Int = 0
var mDesc:String = ""
var title:String = ""

val colorNames = listOf<String>("红色","黄色","绿色","青色","蓝色")
val colors = intArrayOf(Color.RED, Color.YELLOW, Color.GREEN, Color.CYAN, Color.BLUE)
var mSeq:Int = 0
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
ctx = activity
if (arguments != null) {
mPosition = arguments!!.getInt("position", 0)
mInageId = arguments!!.getInt("image_id", 0)
mDesc = arguments!!.getString("desc")
title = arguments!!.getString("title")
}
val view = inflater.inflate(R.layout.show_info, container, false)

view.findViewById<ImageView>(R.id.imageView).setImageResource(mInageId)
view.findViewById<TextView>(R.id.textView).text = mDesc
view.findViewById<Button>(R.id.se).setOnClickListener {
ctx!!.selector("选择颜色", colorNames) {
mSeq = it

val intent = Intent(BlankFragment.EVENT)
intent.putExtra("seq", it)
intent.putExtra("color", colors[it])
ctx!!.sendBroadcast(intent)//发送广播
}
}
return view
}

companion object {
const val EVENT:String = "changeColor"//const,编译期常量
fun newInstance(position:Int, image_id:Int, desc:String, title:String) : BlankFragment {

val fragment = BlankFragment()
val bundle = Bundle()
bundle.putInt("position", position)
bundle.putInt("image_id", image_id)
bundle.putString("desc", desc)
bundle.putString("title", title)
fragment.arguments = bundle
return fragment
}
}
}
  1. 在要接收广播的页面注册receiver
阅读更多