8/23-8/27

8/23-8/27

一周总结报告

8/23-8/27这一周主要是对安卓代码架构和四大组件的学习以及PDX自测。

1.app目录结构:

bulid:存放该项目的构建结果

libs:存放该项目依赖的第三方类库

src:androidTest

    main:java(存放Java或Kotlin源文件)

          res:存放Android项目的各种资源文件drawble(存放XML文件定义的Drawable资源),layout(存放界面布局文件),mipmap-xxx(存放XML文件定义的Drawable资源),values

    test

build.gradle(Gradle构建文件)

.gitigore(该文件配置Git工具忽略管理哪些文件)

注意:drawable与mipmap的区别:mipmap子目录用于保存应用程序启动图标及系统保留的Drawble资源;而drawable子目录则用于保存与项目相关的各种Drawable资源。

2.多语言values文件夹

首先,在res目录下新建values文件夹,根据需要的语言将文件夹命名为对应的名字;

然后,在新建的values语言文件夹中新建strings.xml文件,编写string类型的文本,在布局文件中文本引用语言文件夹中的name;

最后,在设备的设置中切换语言,界面会显示对应国家的语言。

3.on       Create()函数

onCreate()函数是在activity初始化的时候调用的,通常情况下,我们需要在onCreate()中调用setContentView(int)函数填充屏幕的UI,一般通过findViewById(int)返回xml中定义的视图或组件的ID。子类在重写onCreate()方法的时候必须调用父类的onCreate()方法,即super.onCreate(),否则会抛出异常。一个activity启动调用的第一个函数就是onCreate,它主要做这个activity启动时一些必要的初始化工作,这个函数调用完后,这个activity并不是说就已经启动了,或者是跳到前台了。而是还需要其他的大量工作,我们知道:onCreate之后还有onRestart()和onStart()等,实际上onStart()调用完毕了这个activity还没有完全启动,也只是前台可见,直到 onResume() 调用后这个onCreate才算终于启动。

以下是上周学习过程中做的笔记总结归纳,有部分还未学习结束,会继续学习完善:

一、         安卓四大组件

  1. Activity

1)         启动模式

singleInstance模式

在singleInstance这种加载模式下,系统保证无论从哪个Task中启动目标Activity,只会创建一个目标Activity实例,并会使用一个全新的Task栈来加载该Activity实例。

只有一个实例,并且这个实例独立运行在一个activity任务栈中,这个task只有这个实例,不允许有别的Activity存在

  1. Service

1)         概述

Service(服务)是一个一种可以在后台执行长时间运行操作而没有用户界面的应用组件。服务可由其他应用组件启动(如Activity),服务一旦被启动将在后台一直运行,即使启动服务的组件(Activity)已销毁也不受影响。 此外,组件可以绑定到服务,以与之进行交互,甚至是执行进程间通信 (IPC)。 例如,服务可以处理网络事务、播放音乐,执行文件 I/O 或与内容提供程序交互,而所有这一切均可在后台进行,Service基本上分为两种形式:

2)         两种形式:

启动状态: 当应用组件(如 Activity)通过调用 startService() 启动服务时,服务即处于“启动”状态。一旦启动,服务即可在后台无限期运行,即使启动服务的组件已被销毁也不受影响,除非手动调用才能停止服务,已启动的服务通常是执行单一操作,而且不会将结果返回给调用方。

绑定状态: 当应用组件通过调用 bindService() 绑定到服务时,服务即处于“绑定”状态。绑定服务提供了一个客户端-服务器接口,允许组件与服务进行交互、发送请求、获取结果,甚至是利用进程间通信 (IPC) 跨进程执行这些操作。仅当与另一个应用组件绑定时,绑定服务才会运行。多个组件可以同时绑定到该服务,但全部取消绑定后,该服务即会被销毁。

3)         生命周期

被启动的服务的生命周期

如果一个Service被某个Activity 调用 Context.startService 方法启动,那么不管是否有Activity使用bindService绑定或unbindService解除绑定到该Service,该Service都在后台运行。如果一个Service被startService 方法多次启动,那么onCreate方法只会调用一次,onStart将会被调用多次(对应调用startService的次数),并且系统只会创建Service的一个实例。该Service将会一直在后台运行,而不管对应程序的Activity是否在运行,直到被调用stopService,或自身的stopSelf方法。当然如果系统资源不足,android系统也可能结束服务。

被绑定的服务的生命周期

如果一个Service被某个Activity 调用 Context.bindService 方法绑定启动,不管调用 bindService 调用几次,onCreate方法都只会调用一次,同时onStart方法始终不会被调用。当连接建立之后,Service将会一直运行,除非调用Context.unbindService 断开连接或者之前调用bindService 的 Context 不存在了(如Activity被finish的时候),系统将会自动停止Service,对应onDestroy将被调用。

被启动又被绑定的服务的生命周期

如果一个Service又被启动又被绑定,则该Service将会一直在后台运行。并且不管如何调用,onCreate始终只会调用一次,对应startService调用多少次,Service的onStart便会调用多少次。调用unbindService将不会停止Service,而必须调用 stopService 或 Service的 stopSelf 来停止服务。

当服务被停止时清除服务

当一个Service被终止(1、调用stopService;2、调用stopSelf;3、不再有绑定的连接(没有被启动))时,onDestroy方法将会被调用,在这里你应当做一些清除工作,如停止在Service中创建并运行的线程。

  1. BroadCastReceiver
  2. ContentProvider

二、         自定义View

在Android APP中,所有的用户界面元素都是由View和ViewGroup的对象构成的。View是绘制在屏幕上的用户能与之交互的一个对象。而ViewGroup则是一个用于存放其他View(和ViewGroup)对象的布局容器

  1. 实现方式

自定义组合控件:多个控件组合成为一个新的控件,方便多处复用

继承系统View控件:继承自TextView等系统控件,在系统控件的基础功能上进行扩展

继承View:不复用系统控件逻辑,继承View进行功能定义

继承系统ViewGroup:继承自LinearLayout等系统控件,在系统控件的基础功能上进行扩展

继承ViewViewGroup:不复用系统控件逻辑,继承ViewGroup进行功能定义

  1. 绘制流程

OnMeasure()——>OnLayout()——>OnDraw()

第一步:OnMeasure():测量视图大小。从顶层父View到子View递归调用measure          方法,measure方法又回调OnMeasure。

第二步:OnLayout():确定View位置,进行页面布局。从顶层父View向子View的递归调用view.layout方法的过程,即父View根据上一步measure子View所得到的布局大小和布局参数,将子View放在合适的位置上。

第三步:OnDraw():绘制视图。ViewRoot创建一个Canvas对象,然后调用OnDraw()。

View的绘制离不开 Canvas,所以在重写 onDraw 方法的时候,系统传递给我们一个 Canvas 对象,剩下的就是配合一个自己创建的 Paint 去绘制我们想要的界面。

例:

@Override

protected void onDraw(Canvas canvas) {

    super.onDraw(canvas);

    Paint paint = new Paint();

    canvas.drawCircle(50, 50, 50, paint);

}

Canvas中

drawXxx方法族:以一定的坐标值在当前画图区域画图,另外图层会叠加, 即后面绘画的图层会覆盖前面绘画的图层。

clipXXX方法族:在当前的画图区域裁剪(clip)出一个新的画图区域,这个 画图区域就是canvas对象的当前画图区域了。比如:clipRect(new Rect()), 那么该矩形区域就是canvas的当前画图区域。

invalidate()方法 :

请求重绘View树,即draw()过程,假如视图发生大小没有变化就不会调用layout()过程,并且只绘制那些“需要重绘的”视图,即谁(View的话,只绘制该View ;ViewGroup,则绘制整个ViewGroup)请求invalidate()方法,就绘制该视图。

  1. 构造函数

//在java代码里new的时候会用到,不附带任何自定义属性

public TestView(Context context) {

        super(context);

}

//在xml布局文件中使用时自动调用,传入的attrs是在布局文件中设定的

public TestView(Context context, @Nullable AttributeSet attrs) {

        super(context, attrs);

}

//不会自动调用,如果有默认style时,在第二个构造函数中调用

public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {

        super(context, attrs, defStyleAttr);

}

//在第三个构造方法的基础上,额外添加一个style。注意:如果defStyleAttr有效(defStyleAttr不为0或者有定义defStyleAttr),则defStyleRes无效;如果defStyleAttr无效,则defStyleRes有效。defStyleAttr的优先级比defStyleRes高。

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)

public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {

        super(context, attrs, defStyleAttr, defStyleRes);

    }

  1. 自定义属性步骤

(1)自定义一个View

(2)编写vlaues/attrs.xml,在其中编写styleable和item等标签元素

(3)在布局文件中View使用自定义的属性

(4)在View构造方法中通过TypedArray获取

属性优先级(1>2>3>4):

1、直接在layout.xml文件中添加的属性

2、在style中添加的属性

3、defStyleAttr或defStyleRes(二者不会同时有效)

4、theme中添加的属性