Android应用开发学习笔记

2.安卓UI开发

2.1 布局的创建

在Android中程序中的界面是通过布局文件设定的,在每个应用程序创建时会默认包含一个主界面布局,该布局位于res/layout目录中

实际开发中每个应用程序包含多个界面,而程序默认提供一个主界面布局无法满足需求,所以need添加布局

2.2 布局的类型

五大常见布局

1. 线性布局

以水平(默认)或者垂直方向排列

  • 当控件水平排列时,显示顺序依次为从左到右,当控件垂直排列时,显示顺序为从上到下。

    
    
    
  • 当控件水平排列时,控件属性layout_width只能设置成wrap_content(包裹内容让当前控件根据控件内容大小自动伸缩)

  • 当控件水平排列时,如果控件未占满一行,会留白,此时可以利用layout_weight(权重),通过比例调节布局中所以控件的大小

2. 相对布局

通过相对定位排列,即以其他控件或者父容器作为参照物,拜访控件位置

  • 在设计相对布局时,要遵守控件之间的依赖关系,后放入的控件的位置依赖于先放入的控件。

    
    
    
  • 为了让程序适配:

    名称 解释 补充
    px 像素 在屏幕中可以显示的最小元素单位
    pt 磅数 一般作为字体的单位显示
    dp 基于屏幕密度的抽象单位 不同设备由不同的显示效果,根据设备的分辨率的不同来确定控件的尺寸
    sp 可伸缩像素 推荐设置文字大小时使用

3. 帧布局

开辟空白区域,帧里的控件(层)叠加

  • 为每个加入其中的控件创建一个空白区域(称为一帧,每个控件占据一帧)

  • 所以控件都默认显示在屏幕左上角,按照先后放入的顺序重叠摆放,帧布局的大小由内部最大控件决定

    
    
    

    eg:刮刮卡

4. 表格布局

表格形式排列,通过行和列将界面划分为多个单元格,每个单元格都可以添加控件

  • 表格布局需要配合TableRow使用,每一行都是由TableRow对象组成,所以TableRow的数量决定了表格的行数。表格的列数是由包含最多控件的TableRow决定

  • 表格布局属性

    布局属性 功能描述
    android:stretchColumns 该列被拉伸
    android:shrinkColumns 该列被收缩
    android:collapseColumns 该列被隐藏
  • 表格布局控件属性

    控件属性 功能描述
    android:layout_column 设置该单元显示位置
    android:layout_span 设置该单元格占据几行,默认为1行
    
    	
    		

5. 绝对布局

通过xy坐标排列



2.3 常用控件

控件是界面组成的主要元素,是与用户进行直接交互的

常用控件

1. TextView

2. EditText

  • EditText继承自TextView,可以进行编辑操作,将用户信息传递给Android程序,还可以为EditText控件设置监听器,用来测试用户输入的内容是否合法。

    
    

3. Button

用于响应用户的一系列点击事件,使得程序更加流畅完整

  • 指定Button的onClick属性方式

    • 首先在layout文件中指定onClick属性

      android:onClick="click"
      
    • 然后再Activity中实现这个click方法

      public void click(View v){
      	Log.i("指定onClick属性方式","button is clicked");
      }
      
  • 独立类方式

    • 首先为按钮设置监听器

      btn.setOnClickListener(myListener);
      
    • 在onCreate() 方法外实现接口

      onClickListener myListener=new OnClickListener(){
      public void onClick(View v){
      	Log.i("独立类方式","button is clicked")
      }
      }
      
  • 接口方式

    • 首先在当前Activity中实现OnClickListener接口
    • 然后实现接口方法
  • 匿名内部类方式

    在Activity中添加匿名内部类

    btn.seOnClickListener(new View.OnClickListener(){
    public void onClick(View v)
    	{Log.i("匿名内部类方式","button is clicked");}
    });
    

4. RadioButton

为单选按钮,它需要与RadioGroup配合使用,提供两个或多个互斥的选项集

RadioGroup是单选组合框,可容纳多个RadioButton,并把它们组合在一起,实现单选状态





  • 利用setOnCheckedChangeListener()监听RadioGroup 状态,通过if语句判断被选中RadioButton的id
radioGroup.setOnClickedChangeListener(new RadioGroup.OnClickedChangeListener(){
public void onCheckedChange(RadioGroup group,int checkedId)
{
	if (checkedId==R.id.rbtn){
	textView.setText("您的性别是:男");
	}
	else
	{textView.setText("您的性别是:女");}
}
})

5. ImageView

是视图控件,继承自View,其功能是在屏幕中显示图像



2.4 常见对话框

对话框是程序与用户交互的一种方式,通常用于显示当前程序提示信息以及相关说明

常见对话框:

1. 普通对话框

  • 一般只会显示提示信息,并具有确定和取消按钮

    方法名称 功能描述
    setTitle() 设置对话框标体
    setIcon() 设置对话框图标
    setPositiveButton() 给对话框添加确定按钮
    setNegativeButton() 给对话框添加取消按钮
    setMessage() 设置对话框提示信息
    AlertDialog dialog;
    dialog=new AlertDialog.Bulider(this)
    .setTitle("Dialog对话框")
    .setMessage("是否确定退出")
    .setIcon(R.mipmap.ic_launcher)
    .setPositiveButton("确定",null)
    .setNativeButton("取消",null)
    .create();
    dialog.show();
    

2. 单选对话框

单选对话框和RadioButton相似,只能选择一个选项,它是通过AlertDialog对象调用setSingleChoiceItems()方法创建

new AlertDialog.Bulider(this)
	.setTitle("请选择性别")
	.setIcon(R....)
	.setSingleChoiceItems(new String[]{"男""女"},0,new DialogInferface.OnClickListener(){
	public void onClick(DialogInferface dialog,int which){
	
	}
	})
	.setPositiveButton("确定",null)
	.show;

3. 多选对话框

多选对话框通常需要勾选多种选项时使用,创建多选对话框调用 setMultiChioseItems()

new AlterDialog.Bulder(this)
	.setTitle("请添加兴趣爱好")
	.setIcon(R....)
	.setMultiChoiceItems(new String[]{"A","B","C"},null,null)
	.setPositiveButton("确定",null)
	.show

4. 进度条对话框

进度条对话框一般在应用程序实现耗时操作时使用

ProgressDialog prodialog;
prodialog=new ProgressDialog(this);
prodialog.setTitle("进度条对话框");
prodialog.setIcon("....jpg");
prodialog.setMessage("正在下载请稍后。。。");
prodialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
prodialog.show;

5. 消息对话框

是轻量级消息提醒机制,显示在应用程序界面的最上层,一段时间后会自动消失不会打断当前操作,也不会获得焦点

Toast.makeTaxt(this,"Hello,Toast",Toast.LENGTH_SHORT).show();

6. 自定义对话框

创建自定义对话框的流程:

  • 创建布局:创建一个自定义对话框的布局文件(my_dialog.xml),布局中需要设定对话框的标题,对话框内容以及确定和取消按钮
  • 创建自定义对话框:创建一个类MyDialog继承自Dialog类,主要用于初始化自定义对话框中的控件以及响应按钮的点击事件
  • 使用自定义对话框:在MainActivity中,调用MyDialog的构造方法将自定义对话框显示出来

2.5 样式主题

1. 样式

style是一种包含一种或者多种控件的属性集合,可以指定控件高度,宽度,字体大小及颜色等


    

采用自定义样式:



	

2. 主题

theme是应用到整个Acitivity和Application的样式,当设置好主题后,Activity或整个程序中的视图都将使用主题中的属性,当主题和样式中的属性发生冲突时,样式的优先级要高于主题

自定义主题的代码:


	

引用自定义主题代码:


	
		
			...
		
	

3. Activity

3.1 Activity 的创建

Activity是Andriod程序的四大组件之一,为用户提供可视化界面及操作,一个应用程序通常包含多个Activity,每个Activity负责管理一个用户界面,这些界面可以添加多个控件,每个控件负责实现不同功能

  • Android 开发的四大组件分别是
    • 活动(activity),用于表现功能;
    • 服务(service),后台运行服务,不提供界面呈现;
    • 广播接受者(BroadcastReceive),用于接收广播;
    • 内容提供者(ContentProvider),支持多个应用中存储和读取数据,相当于数据库 。

两种创建方式

  • 包名处点击右键选择New-Activity-Empty Activity选择,填写Activity信息,完成创建

  • 包名中点击右键选择New-Java Class 选项,填写Java类名,完成创建,在该类中继承AppCompatActivity,并在清单文件中进行注册,完成Activity的创建

3.2 Activity的生命周期

  • 启动状态:当Activity启动之后便会进入下一状态
  • 运行状态:当Activity处于屏幕最前端,可与用户进行交互
  • 暂停状态:Activity任可见,但无法获得焦点,用户对它的操作没有响应
  • 停止状态:Activity完全不可见,系统内存不足时会销毁该Activity
  • 销毁状态:Activity将被清除内存

生命周期方法:

生命周期方法 用途
onCreate() 在Activity即将可见时调用
onStart() 在Activity即将可见时调用
onResume() Activity获取焦点时调用
onPause() 当前Activity被其他Activity覆盖或锁屏时调用
onStop() Activity对用户不可见时调用
onRestart() Activity从停止状态再次启动时调用
onDestory() Activity销毁时调用
  • 手机横竖屏切换时,系统会根据AndroidMainfest.xml文件中Activity的configChanges属性值不同而调用相应的生命周期方法

  • 没有设置configChanges属性的值时:

    • 当由竖屏切换为横屏时,依次调用的方法依次是:

      onPause(),onStop(),onDestory(),onCreate(),onStart(),onResume()

  • 设置configChanges属性

3.3 Activity的启动模式

1.任务栈

  • 任务栈:一种用来存放Activity实例的容器
  • 特点:先进后出
  • 操作:压栈和出栈

2. standard模式

standard模式是Activity的默认启动方式,每启动一个Activity就会在栈顶创建一个新的实例

3. singleTop模式

singleTop模式会判断要启动的Activity实例是否位于栈顶,如果位于栈顶则直接复用,否则创建新的实例

4. singleTask模式

singleTask模式下每次启动该Activity时,都会检查栈中是否存在当前Activity实例,如果存在则直接使用,并把当前Activity之上的所有实例全部出栈

5. singleInstance模式

singleInstance模式会启动一个新的任务栈来管理Activity实例,无论哪个任务栈中启动该Activity,该实例在整个系统中只有一个

6. 启动模式的设置

  • 通过AndrodMenifest.xml文件为Activity指定启动模式

    
    
  • 通过Intent中设置标志位(addFlags方法)来为Activity指定启动模式

    Intent intent=new Intent();
    intent.setClass(ActivityB.this,ActivityA.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(intent);
    
  • 启动模式的设置

    • Intent.FLAG_ACTIVITY_NEW_TASK

      该标志位标识使用一个新的任务栈来启动一个Activity

    • Intent.FLAG_ACTIVITY_SINGLE_TOP

      该标志位表示使用singleTop模式来启动一个Activity

    • Intent.FLAG_ACTIVITY_CLEAR_TOP

      该标志位表示使用singleTask模式来启动一个Activity

3.4 Activity 之间的跳转

1. Intent

  • 意图,是程序中各组件进行交互的一种重要方式,它不仅可以指定当前组件要执行的动作,还可以在不同组件之间进行数据传递

  • 一般用于启动Activity、Service以及发送广播等,根据开启目标组件的方式不同,Intent可以被分为两种类型:显示意图和隐式意图

2. 显示意图

可以直接通过指定名称开启指定的目标组件

显示调用需要明确的指出被启动的对象的组件信息、包括包名和类名

Intent intent=new Intent(this,Activity02.class); //创建一个Intent对象,其中第一个参数位Context表示当前的Activity对象,第2个参数表示要启动的目标Activity
startActivity(intent);  //调用Activity的startActivity方法启动目标组件

3. 隐式意图

通过指定action和category等属性,系统在分析这些属性信息寻找目标Activity

需要Intent能匹配目标组件的IntentFilter中所设置的过滤信息.如果不匹配将无法启动目标Activity

Intent intent=new Intent();
intent.setAction("cn.itcast.START_ACTIVITY"); //设置action动作,当与清单文件中的action相匹配时,启动目标组件
startActivity(intent);

	
		 //设置action动作,当代码中的action与该action相匹配时启动该组件
		
	

4. IntentFlier(过滤器)

  • 当发送一个隐式intent后,Android系统会将他和程序中的每一个组件的过滤器进行匹配,匹配的属性有action\data\category,需要这三个属性都匹配成功才能唤醒相应的组件

  • action:用于指定Intent对象的动作

    
    	
    	
    
    

    那么只要Intent中的action能够和Activity过滤规则中的任何一个action相同即可匹配成功。

    在清单文件中为activity添加intent-filter标签时,必须添加action属性,否则隐式Intent无法开启该Activity

  • data:指定数据的URI或者数据MIME类型

    
    	
    	
    
    

    隐式Intent携带的data数据只要与IntentFilter中任意一个data声明相同,data属性就匹配成功

  • catagory:用于Activity添加额外信息

    
    	
    	
    
    
    

    隐式Intent中声明的category必须全部能够与某一个IntentFilter中的category匹配才能算匹配成功

    IntentFilter中的category属性数量必须大于等于隐式Intent携带的category数量属性时,才能匹配成功

    如果一个隐式Intent没有携带category属性,那么他就可以通过任意一个Intent-filter的category匹配成功

3.5 Activity中的数据传递

1. 使用Intent提供的putExtra()方法

.putExtra

.getStringExtra

Intent intent=new intent(this,Activity02.class);
intent.putExtra("extra_data","Hello Activity02");//在Activity01中放入数据传送给Activity02
startAcivity(intent);

Intent intent=getintent();
String data=intent.getStringExtra("extra_data");//在Activity02中获取Activity01传递来的数据

2. 使用Bundle类传送数据

在MainActivity中将数据传递给ScendActivity

Intent intent=new Intent();
intent.setClass(this,SecondActivity.class); 
Bundle bundle=new Bundle(); //创建Bundle对象
bundle.putString("useName","sunhf"); //将用户名封装到Bundle对象中
intent.putExtra(bundle); //将Bundle对象封装到Intent对象中
startActivity(intent);

在SecondActivity中获取数据

Bundle bundle=getIntent().getExtra(); //获取Bundle对象
String accound=bundle.getString("userName"); //获取用户名

4. 数据存储

4.1 数据存储方法

Android中的5种数据存储方法

  • 文件存储:是一种常见的方法,与Java中的文件存储类似,都是通过I/O流的形式存储数据
  • SharedProferences:是Android提供的用来存储一些简单的配置信息的一种机制
  • SQLite数据库:Androd自带的一个轻量级数据库,支持基本SQL语法
  • ContentProvider:Android四大组件之一,可以将自己的数据分享给其他应用程序
    • Android 开发的四大组件分别是
      • 活动(activity),用于表现功能;
      • 服务(service),后台运行服务,不提供界面呈现;
      • 广播接受者(BroadcastReceive),用于接收广播;
      • 内容提供者(ContentProvider),支持多个应用中存储和读取数据,相当于数据库
  • 网络存储:是通过网络提供的存储空间来存储/获取数据信息

4.2 文件存储

  • 分为内部存储和外部存储

    内部存储 外部存储
    存储位置 将数据以文件的形式存储到应用种 将数据以文件的形式存储到外部设备上
    存储路径 data/data//目录下 mnt/sdcard/目录下,使用getExternalStoageDirectory()获得根目录
    其他应用操纵该文件时 需要设置权限 不用设置权限,会被其他应用共享
    删除文件 当应用被卸载时,该文件也会被删除 该文件可在本应用外删除,使用前需要确认外部设备是否可用
    操作数据 通过openFileOutput()方法和openFileInput()方法获取FileOutputStream和FileInputStream操作对象 直接使用FileOutputStream和FileInputStream操作对象

1. 内部存储

FileOutputStream fos=openFileOutput(String name,int mode);
FileInputStrean fis=openFileInput(String name);
  • mode取值

    • MODE_PRIVATE:该文件只能被当前程序读写
    • MODE_APPEND:该文件内容可以追加
    • MODE_WORLD_READABLE:该文件的内容可以被其他程序读
    • MODE_WORLD_WRITEABLE:该文件的内容可以被其他程序写
      • Android系统有一套自己的安全模型,默认情况下任何应用创建的文件都是私有的,其他程序无法访问。除非在文件中指定了操作模式为MODE_WORLD_READABLE或者MODE_WORLD_WRITEABLE。如果希望外部文件能被其他程序进行读写操作。需要同时指定MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE权限。
  • 写入

    String fileName="data.txt"; //文件名称
    String content="hello";//保存数据
    FileOutputStream fos=openFileOutput(fileName,MODE_PRIVATE);
    fos.write(content.getBytes());
    fos.close;
    
  • 读取

    String content="";
    FileInputSream fis=null;
    fis=openFileInput("data.txt"); //获得文件输入流对象
    byte[] buffer=new byte[fis.available()];
    fis.read(buffer);
    content=new String(buffer);
    fis.close;
    

2. 外部存储

由于外部设备可能被移除,丢失或处于其他状态,因此在使用外部设备之前必须使用

**Environment.getExternalStorageState()**方法来确认外部设备是否可用。当外部设备可用并且具有读写权限时,那么就可以通过FileInputStream、FileOutputStream对象来读写外部设备中的文件。

4.3 XML解析

三种解析方法

解析方法 补充 缺点
DOM解析 将XML文件中所有内容以DOM树形式存放到内存中,支持删除,修改等功能 消耗内存大
SAX解析 逐行扫描XML文件,读取文件的同时即可进行解析处理,不必等到文件加载结束 无法进行增、删、改等操作
PULL解析 一个开源的Java项目,既可以用于Android应用,也可用于JavaEE程序,Android中以及集成了PULL解析器
  • XmlPullParser:PULL解析器类

    XmlPullParser parser=Xml.newPullParser();//获取PULL解析器
    xmlPullParser.setInput(is,"UTF-8");//设置解析器参数
    int type=xmlPullParser.getEventType();//获得事件类型
    

4.4 JSON解析

  • 对象标识法,是一种轻量级的数据交换格式
  • JSON是基于纯文本的数据格式,他可以传输String,Number,Boolean类型的数据,也可以传输数组,或者Object对象
  • JSON文件的扩展名为.json
  • JSON分为JSON对象和JSON数组两种数据结构

两种解析方式

1. org.json

  • 例如要解析是json数据如下

    {"name":"xiaowang","age":18,"married":forse} //json1
    
    JSONObject jsonObj=new JSONObject(json1);
    String name=jsonObj.optString("name");
    int age=jsonObj.optInt("age");
    booleam married.optBoolean("married");
    
  • 使用org.json解析JSON数组

    例如要解析的JSON数据如下

    [111,11,1] //json2
    
    JSONArray jsonArray=new JSONArray(json2);
    for(int i=0;i

2. Gson

使用Gson库之前,先要将gson.jar添加到项目中,并创建JSON数据对应的实体类Person

  • 使用Gson解析json对象

    Gson gson=new Gson();
    Person person=gson.fromJson(json1,Person.class);//Person.class与json对应的实体类
    
    
  • 使用Gson解析json数组

    Gson gson=new Gson();
    Type listType=new TypeToken>(){}.getType;//指定数据类型
    Listages=gson.fromJson(json2,listType);
    
    

4.5 SharedPreferences

  • 是Android平台上一个轻量级的存储类,用于存储应用程序的配置参数,如文件名、密码等
  • 通过key/value(键值对)的形式将数据保存到XML文件中,文件存放在/data/data//shared_prefs目录下
  • value值只能是 float\int\long\boolean\String\StringSet 类型数据

1. 将数据存入ShardPreferences中

getShardPreferences(name,mode)
//第一个参数用于指定该文件的名称,名称不用带后缀
//第二个参数指定文件的操作模式

文件的MODE:

  • MODE_PRIVATE:该文件只能被当前程序读写
  • MODE_APPEND:该文件内容可以追加
  • MODE_WORLD_READABLE:该文件的内容可以被其他程序读
  • MODE_WORLD_WRITEABLE:该文件的内容可以被其他程序写
    • Android系统有一套自己的安全模型,默认情况下任何应用创建的文件都是私有的,其他程序无法访问。除非在文件中指定了操作模式为MODE_WORLD_READABLE或者MODE_WORLD_WRITEABLE。如果希望外部文件能被其他程序进行读写操作。需要同时指定MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE权限。
ShardPreferences sp=getShardPreferences("data",MODE_PRIVATE);//得到ShardPreferences对象
ShardPreferences.Editor editor=sp.edit(); //获得ShardPreferences编译器
editor.putString("name","王"); //使用编译器存储数据
editor.putInt("age",18);
editor.commit(); //提交保存数据

2. 读取和删除数据

  • 读取数据

    ShardPreferences sp=getShardPreferences("data",MODE_PRIVATE);
    String data=sp.getString("name","");
    
    
  • 删除数据

    editor.remove("name"); //根据键 删除数据
    editor.clear();//删除所有数据
    editor.commit;
    
    

    5. SQLite数据库

5.1 简介

SQLite特点:

  • SQLite是一个轻量级数据库,占用资源非常低
  • SQLite是遵守ACID的关系型数据库管理系统
    • 原子性
    • 一致性
    • 隔离性
    • 持久性
  • SQLite保存数据时,支持NULL(零),INTEGER(整型),REAL(浮点数字),TEXT(字符串文本)和BLOB(二进制对象)五种数据类型

5.2 数据库的创建

1. 创建数据库

SQLiteOpenHelper类:是SQLiteDatabase的一个帮助类,用于数据库创建和版本的更新,一般是建立一个类去继承他,并实现他的onCrete()和onUpgrade()

方法名 方法描述
SQLiteOpenHelper() 构造方法
onCreate() 创建数据库时调用
onUpgrade() 版本更新时调用
getReadableDatabase() 创建或打开一个只读数据库
getWriteableDatabase() 创建或打开一个读写数据库

5.3 数据库的使用

1. 添加数据

(long)insert(String table,String nullCoiumnHack,ContentValues values)
返回:添加的记录条数,不成功则返回-1
参数:数据表名;插入某个字段值为空时,设置字段值为null;键值对形式存储的对象
public void insert(String name,String sNumber){
//获取可读写对象
	SQLiteDatabase db=helper.getWriteableDatabase(); 
//创建ContentValues对象并将数据添加到对象中
	ContentValues values=new ContentValues(); 
	values.put("name",name);
	values.put("age",sNumber);
//调用insert()将数据添加到数据库中
	long id=db.insert("information",null,values);
	db.close();
}

2. 修改数据

(int)update(String table,ContentValues values,Sting whereClause,String[] whereArgs)
返回:更新的记录有几条
参数:表名;更新的值:ContentValues对象;定位条件——占位符;条件的值
publis int update(String name,String sNumber){
	SQLiteDatabase db=helper.getWriteableDatabase();
	ContentValues values=new ContentValues();
	values.put("sNumber",sNumber);
	int number=db.update("information",values,"name=?",now String[]{name});
	db.close;
	return number;
}

3. 删除数据

(int)delete(String table,String whereClause,String[]whereArgs)
返回:被删除的记录条数
参数:表名;条件;条件的值
public int delete(String sNumber){
	SQLiteDatabase db=helper.getWritezbleDatabase();
	int number=db.delete("information","sNumber=?",new String[]{sNumber});
	db.close();
	return number;
}

4. 查询数据

(Cursor)query(String table,String() columns,String selection,String[]selectionArgs,String groupBy,String having,String orderBy)
返回:结果集

cursor(游标)

方法名称 方法描述
getCount() 总记录条数
isFirst() 判断是否是第一条记录
isLast() 判断时候是最后一条记录
moveToFirst() 移动到第一条记录
moveToLast() 移动到最后一条记录
move(int offset) 移动到指定的记录
moveToNext() 移动到上一条记录
moveToPrevious() 移动到吓一条记录
getColmnsIndex() 获得指定列的索引值

5. 事务

  • 数据库事务是一个对数据库执行工作单元,是针对数据库的一组操作,他可以由一条或者多条SQL语句组成
  • 事务是以逻辑顺序完成的工作单位或序列,可以由用户手动操作完成,也可以由数据库程序自动完成。
//开启数据库事务
db.beginTransation();
//设置数据库标志位成功,当事务结束时,提交事务
}
catch(Exception e){
	Log.i("事务处理失败",e.toString());
}
//关闭数据库事务
db.close();

5.4 数据展示控件

1. ListView 的简单使用

  • ListView以列表的形式展示数据内容,并且能够根据列表的高度自适应屏幕显示
属性名称 功能描述
android:listSelector 当条目被点击后,改变条目的背景色
android:divider 设置分割线的颜色
android:dividerHeight 设置分割线的高度
android:scrollbars 是否显示滚动条
android:fadingEdge 去掉上下的黑色阴影

2. 常用数据适配器(Adapter)

  • 数据适配器时数据和视图之间的桥梁,类似于一个转换器,将复杂的数据转化成用户可以接收的方式
  • 常用的数据适配器
    • BaseAdapter
    • SimpleAdapter
    • ArrayAdapter

3.BaseAdapter

BaseAdapter(抽象类)即基本的适配器,自定义适配器继承BaseAdapter,需要实现四个方法

方法名称 功能表述
public int getCount() 得到Item条目的总数
public Object getItem(int position) 根据postion得到某个Item的对象
public long getItemId(int position) 根据position得到某个Item的id
public View getView(int position,View convertView,ViewGroup) 得到相应position对应的Item视图,position是当前Item的位置,convertView用于复用旧视图

4. SimpleAdapter

SimpleAdapter继承自基本适配器,实现了BaseAdapter的四个抽象方法并进行了封装

public SimpleAdapter(Context context,List>data,int resource,String[]from,int[] to)

5. ArrayAdapter

ArrayAdapter也是基本适配器的子类,通常用于适配TextView控件

6. ListView 的优化

两种优化方法

  • 复用convertView
  • 使用ViewHolder类

6. BroadcastReceiver(广播接收者)

Android 开发的四大组件分别是

  • 活动(activity),用于表现功能;
  • 服务(service),后台运行服务,不提供界面呈现;
  • 广播接受者(BroadcastReceive),用于接收广播;
  • 内容提供者(ContentProvider),支持多个应用中存储和读取数据,相当于数据库 。

6.1 广播接收者简介

  • 广播接收者是通过Binder机制在AMS中进行注册的

  • 广播接收者是通过Binder机制向AMS发送广播

  • AMS查找符合相关条件的广播接收者,将广播发送到相应的消息循环队列中

  • 执行消息循环时获取到此广播,会回调广播接收者中的onReceive()方法并在该方法中进行相关处理

  • Android系统中内置了很多广播,例如手机开机完成

  • 为了监听来自系统或应用程序的广播事件,Android系统提供了BroadcastReceiver组件

  • 当Android系统中产生一个广播事件时,可以有多个对应的广播接收者接收并进行处理

6.2 广播接收者入门

创建
在onReceive()中实现操作

public class MyReceiver extends BoastcastReceiver{
	public MyReceiver(){
	}
	public void onReceiver(Context context,Intent intent){
	//实现广播接收者的相关操作
		throw new UnsupportedOperationException("Not yet implemented");
	}
}

静态注册广播:只要设备处于开启状态,广播接收者就能接收到广播



对于应用程序监听SMS Intent广播,首先需要添加RECEIVEE_SMS权限


protected void onCreate(Bundle savedInstanceState){
	super.onCreate(savedInstanceState);
	MyReceiver receiver=new Myreceiver();
	//实例化过滤器并设备要过滤的广播
	String action="android.provider.Telephony.SMS_RECEIVED";
	IntentFilter intentFile=new IntentFile(action);
	//注册广播
	registerReceiver(receiver,intentFile);
}
protected void onDestory(){
	super.onDestory();
	//当Activity销毁时,取消注册
	unregisterReceiver(receiver);
}

6.3 自定义广播

  • 当系统提供的广播不能满足实际需求时,可以自定义广播,同时需要编写对应的广播接收者

  • 当自定义广播发送消息时,会存储到公共消息区,而公共消息区中如果存在对应的广播接收者,就会及时接收这条消息

自定义广播

Android8.0+后,限制隐式广播-

  • 广播接收者静态注册的情况下,发送隐式广播需要设置标志位突破隐式广播限制

    Intent intent=new intent();
    intent.addFlags(0x01000000);
    intent.setActin("help,help,help");
    sendBroadcast(intent);
    
  • 广播接收者静态注册的情况下,发送显示广播

    Intent intent=new Intent();
    intent.setComponent(new ComponentName("广播接收者的包名","广播接收者的完整类名"));
    sendBroadcast(intent);
    
  • 动态注册广播接收者

    Intent intent=new Intent();
    intent.setAction("help,help,help");
    sendBroadcast(intent);
    

6.4 广播类型

  • android提供了两种广播类型,有序广播和无需广播

  • 有序广播:按照接收者的优先级结束,只有一个广播接收者能接收消息,在此广播接收者中逻辑执行完毕后,才会继续传递。

    //数值越大,优先级越高
    
    
//动态注册MyReceiver广播
Myreceiver one=new MyReceiver();
IntentFlier filer=new IntentFiler();
filter.setPriority(100);

发送有序广播:sendOrderedBroadcast()

中断广播:abortBroadcast()

  • 无序广播即为我们平时经常使用的广播,其主要是通过public abstract void sendBroadcast (Intent intent)方法进行发送,并通过intent传递数据。 无序广播不可以被拦截,不可以被终止,不可以被修改,无序广播任何接收者只要匹配条件都可以接收到,无优先级问题。

7. Service

7.1 服务的创建

Android 开发的四大组件分别是

  • 活动(activity),用于表现功能;
  • 服务(service),后台运行服务,不提供界面呈现;
  • 广播接受者(BroadcastReceive),用于接收广播;
  • 内容提供者(ContentProvider),支持多个应用中存储和读取数据,相当于数据库 。

service是android四大组件之一,,能够在后台长时间执行操作且不提供用户界面的应用程序组件,service可以和其他组件进行交互,一般是由Activity启动,但是并不依赖与活动。

当活动的生命周期结束时,Service任然会继续运行,直到自己的生命周期结束为止

Service通常被称为“后台服务”,具体是指其本身的运行不依赖于用户可视的UI界面,此外,它的应用场景还有两个,后台运行和跨进程访问。

1. 服务的创建

  • 服务的创建和广播接收者类似,同样在程序包名上点击右键选择new service ,在弹出窗口输入服务的名称即可完成创建

  • 服务创建完成后,android studio会自动在AndroidMainfesr.xml中对服务进行注册

  • 自动创建java类继承Service类,来创建服务

  • 若采用自行创建java类继承Service类的方式创建服务,则需要手动在清单文件中进行注册

    清单文件


	
		    //表示该服务能够被其他应用程序组件调用
		
	

7.2 服务的生命周期

7.3 服务的启动方式

  • 服务的启动方式
启动方式 终止方法
startService() 需要自身调用stopSelf()方法或者其他组件调用stopService()方法,服务才能停止
bindService() 需要调用onUnbind()方法接触绑定之后才会销毁

使用不同的方法启动服务,其生命周期也是不同的

1. startService方法启动

startService() 方法启动服务,服务会长期在后台运行,并且服务的状态与开启者的状态没有关系,即启动服务的组件已经被销毁,服务会依然运行

开启服务
Intent intent=new Intent(this,MyService.class);
startService(intent);
关闭服务
Intent intent=new Intent(this,MyService.class);
stopService(intent);

2. bindService方式启动

通过bindService()方法启动服务时,服务会和组件绑定,当服务中的onUnbind()方法调用时,这个服务就会被销毁

绑定服务
Intent intent=new Intent(this,MyService);
//Intent service用于指定要启动的SC,
//ServiceConnection conn用于监听调用者与SC之间的连接状态,
//int flags用于绑定时是否自动创建Service
bindService(Intent service,ServiceConnection conn,int flags)

ServiceConnection conn:监听器,监听调用者与Service之间的连接

class MyServiceConn implements ServiceConnection{
	public void onServiceConnected(ComponentName compoentName,IBinder iBinder){}
	public void onServiceDisconnected(ComponentName componentName){}
}

int flags用于绑定时是否自动创建Service,0表示不自动创建,BIND_AUTO_CREATE表示自动创建

解除绑定
unbindServce(conn);

为什么有了startService()还要BindService()?

为了调用服务里的方法

​ 定义IBinder对象

​ 在onBind()方法内返回IBinder对象

​ bindService()绑定服务,获取IBinder对象,调用服务里方法

3. 混合方式开启服务

startService()方法开启 bindService()方法开启
一旦开启,未调用stopService()关闭服务,会一直在后台运行 与调用组件同生共死,绑定服务后,返回Binder对象,可调用服务里的方法

混合开启服务的步骤:

  • startService():开启服务,保证服务可以长期在后台运行
  • bindService():绑定服务,获取”IBinder“对象
  • unbindService():解绑夫区,但服务未销毁

7.4 服务的通信

服务方式
本地服务通信 本地服务通信是指应用程序内部的通信,需要使用IBinder对象进行本地服务通信
远程服务通信 远程服务通信是指两个应用程序之间的通信,远程服务通信是通过AIDL实现的

你可能感兴趣的:(android,学习)