文章目录
未写完…本文暂无参考价值
Android 系统架构
Android APP架构
APP工程目录组成
编写APP代码流程
- 画UI
- 根据UI编写具体代码实现功能
- APP测试
- 发布APP
Android 常用布局
Android 四大组件
四大组件都不能自己去new一个对象出来,需要使用清单文件,让系统帮我们创建对象。
1.活动(Activity)
用于与用户交互。
创建activity
- 写一个类继承Activity类
- 重写onCreate()方法做,并在onCreate()方法中调用setContentView()方法把activity的界面给呈现给用户,然后再做一些初始化工作。
- 在AndroidMainfest.xml文件中配置对应的activity节点(每创建一个activity,系统都会自动在AndroidMainfest.xml文件中生成一个activity节点,需要程序员再去根据activity的具体情况做配置)
方法
onClick()
监听按钮点击事件
生命周期
四大状态:
1)处于前台状态:可见,可以与用户进行交互(可以操作)
2)处于暂停状态:可见,不可交互
3)处于停止状态:不可见,不可交互
4)处于销毁状态:activity进程被系统杀死或者被调用finishi()方法主动退出了程序
2.广播接收者(Broadcast Rceivers)
用来接收sendBroadcat()方法发出来的广播。可以通过intent传递数据。是个抽象类。作用范围仅在当前手机中有效(系统会把当前做的重要操作,通过广播告诉手机里的所有APP,比如开机,收到短信,拨打了电话,安装了SD卡等等)
方法
onReceive()
监听广播,随时准备接收系统发出来的广播
getResultData()
获取广播的数据
setResultData()
对获取到的广播数据进行修改
3.服务(Services)
进程
当APP运行之后,系统会为其创建一个进程。一般情况下,一个应用对应一个Linux进程,这个进程在一开始的时候只有一个线程(主线程)。默认情况下,所有的组件都运行在同一个线程中(即同一个进程中),四大组件都运行在主线程中。
1)Foreground process 前台进程
可见可操作。(activity执行了onResume之后,并且留在了这个状态或正在被用户操作)。前台进程几乎不会被系统杀掉。
2)Visable process可视进程
可见但不可操作。只有当前台进程内存不够的时候,才会杀死可视进程。
4.内容提供者(Content Provider)
APP把自己的数据库暴露给别人。如通讯录。
APP测试
一款好的APP是测出来的,不是开发出来的。
测试是为了寻找bug,bug分为两种:
崩溃 当崩溃率高于4%时,就已经很高了,要是高于5%,则几乎无用户了
逻辑bug 能使用,但是运行结果并非预期
测试方法:
黑盒测试:不可见代码的测试,如:自动化测试
白盒测试:可见代码的测试,大多是由测试员或者程序员自己测试,如:单元测试
从测试粒度 ,可分为:
单元测试:对单个方法进行测试
集成测试:将多个方法集合到一起进行测试
系统测试:对整个系统进行测试
从暴力程度 ,可分为:
压力测试:对程序进行指定强度的运行次数测试叫做压力测试。Android SDK工具中有一个工具叫monkey,专门用于压力测试
冒烟测试:一直测试到系统挂掉叫冒烟测试。
Android UI组件
Android Dialog、PopupWindow
Android Activity和Fragment
Activity类
- 呈现给用户的APP界面即一个Activity的子类。
- 每一个界面是一个Activity的子类,在子类中具体去画UI、实现功能和界面跳转(即跳转到另一个Activity子类中)。
- 每当一个Activity被创建的时候,紧接着系统都会自动去调用onCreate()方法。
Activity类中的方法
onCreate()
当Activity被创建时会调用onCreate()方法,做初始化工作,因此需要根据每个Activity的不同去重构onCreate()方法接着在onCreate()方法中调用setContentView()方法,将Aactivity对应的布局文件展示到屏幕中,让用户能看到当前Activity的界面。
setContenView()
将布局文件加载到内存中并展示给用户,传入的参数为布局文件在R.java文件中声明的对应标签。如:R.layout.activity_main
findViewByID()。
通过各个对象的ID寻找到对象,返回值为View对象。View类是所有安卓控件的父类。当需要给控件赋值,将对象的地址赋给控件时,可以使用该方法。
starActivity(i)
传入一个Intent类的对象,并跳转到该对象所指向的新activity。
隐式意图:
以点击拨号按钮,然后跳转到拨打电话界面为例。代码如下:
public void onClick(View v)
{
Intent intent = new Intent(); //创建一个Intent对象(意图对象)
intent.setAction(Intent.ACTION_CALL); //给意图设置一个动作
intent.setData(Uri.parse("tel:"+110)); //给意图设置数据为110
starActivity(intent); //跳转到拨打110的界面
}
上述示例为调用系统以及内置定义好的action。如果需要关联自定义的action,则如下:
//在清单文件中配置要跳转到的activity
<activity
android:name="...."> <!--指明该节点对应的是哪一个activity-->
<intent-filter>
<action android:name="com.test.nextActivity" />
<category android:name="android.intent.category.DEAFAULT" />
<data android:scheme="testt" />
</intent-filter>
</activity>
-------------------------------------------------------------------------
//在主activity中编写跳转代码
public void onClick(View v)
{
Intent intent = new Intent();
intent.setAction("com.test.nextActivity"); //即传入在清单文件中定义的action
intent.setData(Uri.parse("testt:"+123456)); //根据清单文件中定义的数据协议(testt)来写
starActivity(intent);
}
上述代码通过对另一个activity在清单文件中的意图过滤器标签< intent-filter >…< /intent-filter >所有标签的匹配,如果都匹配上了,则可以正确跳转到该activity。该方法称为隐式意图。
注意:
- < category android:name=“android.intent.category.DEAFAULT” />标签为默认设置,不需要在代码中匹配,如果没有该标签,则无法使用隐式意图的方式跳转
- 一个activity的清单文件可以配置多对意图过滤器,只要完全匹配上其中一对,就可以正确跳转
显示意图:
配置Activity清单文件
标签
- < activity … > … < /activity >
每创建一个新的Activity类,系统都会自动在AndroidMainfest.xml清单文件中自动添加一对< activity > … < /activity >标签activity标签是嵌套在application标签内的。标签中有多个属性。属性写在< activity >标签内。其他标签嵌套写在activity标签对之间。如:
<application 属性 属性 属性>
<activity
android:name="..." <!-- activity标签的name属性 -->
android:label="..."> <!-- activity标签的label属性 -->
<intent> <!-- 嵌套标签 -->
< action android:name="android.intent.action.MAIN"/ > <!-- 嵌套标签 -->
< category android:name="android.intent.category.LAUNCHER" />
</intent>
</activity >
</application>
activity标签的属性
a)name
用来指明当前activity节点多对应的activity代码。
b) label
用来定义activity在桌面显示给用户看时的名字(相当于定义APP的名称)
c)icon
展示给用户的图标。如果activity标签下没有icon属性,会自动往上一层标签寻找(即寻找application标签的icon属性。)
-
< intent-filter > … < /intent-filter >
意图标签,用来表示Activity的启动意图。嵌套在< activity > … < /activity >标签之中 -
< action android:name=“android.intent.action.MAIN”/ >
表明该Activity为主Activity。该标签嵌套在< intent-filter > … < /intent-filter >标签之中 -
< category android:name=“android.intent.category.LAUNCHER” />
表示该Activity是用启动器来启动(即会在手机桌面生成APP的图标,以供用户点击,用户点击之后则会调用启动器来启动)。该标签嵌套在< intent-filter > … < /intent-filter >标签中
Android 事件机制
当用户看到界面的时候,即看到的是布局和布局中的各个控件。用户对控件的操作就叫做事件。所以我们需要给控件添加事件处理机制。
点击事件
首先先对控件进行事件的监听,判断是否有事件发生,再根据发生的响应事件进行不同的处理。
setOnClickListener(l)
接受一个对象参数,这个参数是OnClickListener类,这个类是一个接口(android.view.View.OnClickListener),需要实现。接口中有一个方法叫做onClick(),当控件被点击的时候就会调用这个方法。
onClick(View v)
在onClick()方法中对点击事件做具体处理。
当控件被点击时,控件对象会被当做参数View v传递进onClick()方法中。
假如有多个控件,需要确认被点击的控件是哪一个,可以使用v.getID()函数去获取到控件的ID,再根据ID的不同做出不同的响应。如下
btn_XXX.setOnClickListener(this); /*假如有一个Button控件btn_XXX,并给btn_XXX设置监
听器,当控件被点击时,则会调用onClick()方法。
@override
public void onClick(View v) //onClick方法的具体实现
{
int id = v.getID(); //变量id即可获取到控件对象btn_XXX的ID
switch (id)
{
case R.id.button1:
...
break;
case R.id.button2:
...
break;
...
}
}
点击事件的四种写法
- 创建子类实现OnClickListener接口,控件调用setOnClickListener方法,将创建的子类传给setOnClickListener方法即可对控件进行监听。
- 匿名内置类的写法:控件调用setOnClickListener方法,在给setOnClickListener传递参数的时候再new一个匿名内置类给setOnClickListener方法
- Activity实现接口方法:
public class MainActivity extends Activity implements OnclickListener
{
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState)
{
//把布局文件(用户界面)加载到内存并显示在屏幕上
setContentView(R.layout.activity_main);
//找到控件,先定义一个相应控件类型的引用变量,将控件的地址赋给引用变量
Button btn_XXX = (Button) findViewByID(R.id.button1);
//给控件添加监听器(即调用控件的setOnClickListener()方法对控件进行监听)
btn_XXX.setOnClickListener(this); /*这里给setOnClickListener()方法传入的值为this
因为该类在定义的时候对接口OnclickListener进行了实现
实现的是onClick()方法,在后面具体实现
因为是在这个类里实现的,所以直接引用这个类,故用的this*/
}
@override
public void onClick(View v)
{
//具体实现方法的代码
}
}
}
- 布局文件添加onClick属性
在布局文件对应的部件中加入onClick标签,并自定义赋值。如下代码第8行,赋值为call
/*在 activity_main.xml 文件中*/
...
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@+id/editText1"
android:onClick="call"
android:text="我是一个按钮"/>
...
然后在Java源码中进行函数调用
/*在 MainActivity.java 文件中*/
public class MainActivity extends Activity
{
@override
protected void onCreate(Bundle saveInstanceState)
{
super.onCreate(saveInstanceState);
//显示布局到屏幕上
setContentView(R.layout.activity_main);
}
public void call(View v)
{
/*调用call函数
在布局中为Button部件添加了onClick标签,并赋值为call
当Button部件被点击的时候,则会在当前Activity下调用call()方法
因此,在call()方法中对点击事件编写具体处理的代码即可
注意:该函数的参数必须是View类型的
*/
}
}
- 总结:
a. 在实际编写代码的时候,尽量不要使用第四种方法。因为这种写法,call()方法在代码中没有被调用,假如逻辑很复杂,在多人合作的代码中,别人在阅读的时候发现有一个没有被调用的方法,会难以理解。当想起来是对点击事件的响应函数,还得去布局文件找到对应的标签,非常麻烦、难以维护。只有自己一个人在写一些小demo的时候,再尝试去使用这种方式,与其他人合作开发,尽量不要如此编写。
b. 如果一个activity中有多个部件可以被点击,则可以使用第一种或者第三种方式,再通过getID()方法获取部件,再对点击事件进行响应。
c. 如果只有一个部件可以被点击,则使用第二种方法,方便快捷。