实例解析Android系统中的ContentProvider组件用法

ContentProvider为Android四大组件之一,主要用来应用程序之间的数据共享,也就是说一个应用程序用ContentProvider将自己的数据暴露出来,其他应用程序通过ContentResolver来对其暴露出来的数据进行增删改查。
ContenProvider与ContentResolver之间的对话同过Uri(通用资源标识符),一个不恰当的比喻就好像浏览器要显示一个网页要有一个东西发送请求,这相当于ContentResolver,你要拿东西就要知道去哪里拿,你就得知道服务器的域名或网址,而这个网址就相当于Uri,当到达服务器的时候服务器要有个东西来处理,这就相当于ContenProvider。

A程序通过ContenProvider来暴露数据的基本步骤:
1、实现一个ContenProvider的子类,并重写query,insert,update,delete等这几个方法,
2、在androidmanifest.xml中注册ContenProvider,指定的android:authorities属性
B程序通过ContentResolver来操作A程序暴露出来的数据的基本步骤
1、通过content的getContentResolver()来获取ContentResolver对象
2、通过ContentResolver对象来query,insert,update,delete来进行操作
在实现query,insert,update,delete时有一个重要的参数Uri类,Uri一个中要的方法Uri.parse(String str)用来解析str字符串,而str字符串格式一般都有A程序提供给B程序,B程序按照指定的格式去请求 。比如:content//:com.android.xiong.ConentProviderTestA.firstContentProvider/xiong 其格式一般分为三个部分:content//:这部分是固定不变的 而com.android.xiong.ConentProviderTestA.firstContentProvider表A程序在androidmanifest.xml注册的android:authorities属性,xiong则表示资源部分

<provider android:name="com.android.xiong.conentprovidertesta.FirstContentProvider" android:authorities="com.android.xiong.ConentProviderTestA.firstContentProvider" android:exported="true" > </provider>

实例如下

A程序:
UserInfo.java

package com.android.xiong.conentprovidertesta; import android.content.ContentProvider; import android.content.ContentValues; import android.content.UriMatcher; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.net.Uri; public class FirstContentProvider extends ContentProvider { // UriMatcher类主要用来匹配Uri private static final UriMatcher uriMatcher = new UriMatcher( UriMatcher.NO_MATCH); private MySqlite mysqlite; static { // 注册向外部程序提供的Uri uriMatcher.addURI(UserInfo.AUTOR, "userinfo", 1); uriMatcher.addURI(UserInfo.AUTOR, "userinfoall", 2); } //删除数据 @Override public int delete(Uri uri, String selection, String[] selectionArgs) { int number = 0; if (uriMatcher.match(uri) == 1) { // 根据条件删除数据,并获取删除的行数 number = mysqlite.getReadableDatabase().delete("user_info", selection, selectionArgs); } // 通知数据已经改变 getContext().getContentResolver().notifyChange(uri, null); return number; } @Override public String getType(Uri uri) { return null; } //插入数据 @Override public Uri insert(Uri uri, ContentValues values) { String name = values.getAsString(UserInfo.User.NAME).toString(); String age = values.getAsInteger(UserInfo.User.AGE).toString(); String maxId = "select max(id) id from user_info"; Cursor cursor = mysqlite.getReadableDatabase().rawQuery(maxId, null); cursor.moveToFirst(); int userid = cursor.getInt(0) + 1; if (uriMatcher.match(uri) == 1) { mysqlite.getWritableDatabase().execSQL( "insert into user_info values(?,?,?)", new String[] { String.valueOf(userid), name, age }); } return uri; } // 连接数据库 @Override public boolean onCreate() { mysqlite = new MySqlite(getContext(), "userinfo.db", null, 1); return true; } //查询数据 @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteDatabase sqlite = mysqlite.getReadableDatabase(); String str = "select name,age from user_info"; if (uriMatcher.match(uri) == 1) { str += " where " + selection; } Cursor cursor = sqlite.rawQuery(str, selectionArgs); return cursor; } //修改数据 @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { SQLiteDatabase sqlite = mysqlite.getReadableDatabase(); int number = 0; if (uriMatcher.match(uri) == 1) { number = sqlite.update("user_info", values, selection, selectionArgs); } return number; } }

FirstContentProvider.java

package com.android.xiong.conentprovidertesta; import android.content.ContentProvider; import android.content.ContentValues; import android.content.UriMatcher; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.net.Uri; public class FirstContentProvider extends ContentProvider { // UriMatcher类主要用来匹配Uri private static final UriMatcher uriMatcher = new UriMatcher( UriMatcher.NO_MATCH); private MySqlite mysqlite; static { // 注册向外部程序提供的Uri uriMatcher.addURI(UserInfo.AUTOR, "userinfo", 1); uriMatcher.addURI(UserInfo.AUTOR, "userinfoall", 2); } //删除数据 @Override public int delete(Uri uri, String selection, String[] selectionArgs) { int number = 0; if (uriMatcher.match(uri) == 1) { // 根据条件删除数据,并获取删除的行数 number = mysqlite.getReadableDatabase().delete("user_info", selection, selectionArgs); } // 通知数据已经改变 getContext().getContentResolver().notifyChange(uri, null); return number; } @Override public String getType(Uri uri) { return null; } //插入数据 @Override public Uri insert(Uri uri, ContentValues values) { String name = values.getAsString(UserInfo.User.NAME).toString(); String age = values.getAsInteger(UserInfo.User.AGE).toString(); String maxId = "select max(id) id from user_info"; Cursor cursor = mysqlite.getReadableDatabase().rawQuery(maxId, null); cursor.moveToFirst(); int userid = cursor.getInt(0) + 1; if (uriMatcher.match(uri) == 1) { mysqlite.getWritableDatabase().execSQL( "insert into user_info values(?,?,?)", new String[] { String.valueOf(userid), name, age }); } return uri; } // 连接数据库 @Override public boolean onCreate() { mysqlite = new MySqlite(getContext(), "userinfo.db", null, 1); return true; } //查询数据 @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { SQLiteDatabase sqlite = mysqlite.getReadableDatabase(); String str = "select name,age from user_info"; if (uriMatcher.match(uri) == 1) { str += " where " + selection; } Cursor cursor = sqlite.rawQuery(str, selectionArgs); return cursor; } //修改数据 @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { SQLiteDatabase sqlite = mysqlite.getReadableDatabase(); int number = 0; if (uriMatcher.match(uri) == 1) { number = sqlite.update("user_info", values, selection, selectionArgs); } return number; } }

MySqlite.java

package com.android.xiong.conentprovidertesta; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlite.SQLiteOpenHelper; public class MySqlite extends SQLiteOpenHelper { static final String sql = "create table user_info(id int,name varchar(30),age int)"; public MySqlite(Context context, String name, CursorFactory factory, int version) { super(context, name, factory, version); // TODO Auto-generated constructor stub } @Override public void onCreate(SQLiteDatabase db) { //创建数据表 db.execSQL(sql); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // TODO Auto-generated method stub } }

MainActivity.java

package com.android.xiong.conentprovidertesta; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlite.SQLiteOpenHelper; public class MySqlite extends SQLiteOpenHelper { static final String sql = "create table user_info(id int,name varchar(30),age int)"; public MySqlite(Context context, String name, CursorFactory factory, int version) { super(context, name, factory, version); // TODO Auto-generated constructor stub } @Override public void onCreate(SQLiteDatabase db) { //创建数据表 db.execSQL(sql); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // TODO Auto-generated method stub } }

activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity" > <TextView android:id="@+id/txt1" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:text="添加信息" android:textSize="20dp" /> <EditText android:id="@+id/ed1" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="添加name" /> <EditText android:id="@+id/ed2" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="添加age" android:inputType="number" /> <Button android:id="@+id/bt1" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="提交数据" /> <ListView android:id="@+id/lists" android:layout_width="match_parent" android:layout_height="wrap_content" > </ListView> </LinearLayout>

item.xml

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <TextView android:id="@+id/item_txt1" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <TextView android:id="@+id/item_txt2" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout>

B程序
UserInfo.java

package com.android.xiong.contentprovidertestb; //向外部程序提供一个工具类 public class UserInfo { // 获取ContentProvider的“域名” public static final String AUTOR = "com.android.xiong.ConentProviderTestA.firstContentProvider"; //定义一个静态内部类,提供ContentProvider可操作的列 public static final class User { public static final String ID="id"; public static final String NAME="name"; public static final String AGE="age"; //定义该content提供服务的一个Uri public static final String uri="content://"+AUTOR+"/userinfo"; public static final String uriall="content://"+AUTOR+"/userinfoall"; } }

MainActivity.java

package com.android.xiong.contentprovidertestb; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import android.app.Activity; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.ListView; import android.widget.ScrollView; import android.widget.SimpleAdapter; import android.widget.Toast; public class MainActivity extends Activity { private Button bt1, bt2, bt3, bt4; private EditText ed1, ed2; private ListView list1; private ScrollView sc1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bt1 = (Button) findViewById(R.id.bt1); bt2 = (Button) findViewById(R.id.bt2); bt3 = (Button) findViewById(R.id.bt3); bt4 = (Button) findViewById(R.id.bt4); ed1 = (EditText) findViewById(R.id.ed1); ed2 = (EditText) findViewById(R.id.ed2); list1 = (ListView) findViewById(R.id.list); // 显示所有数据 list1.setAdapter(adapter(0)); sc1 = (ScrollView) findViewById(R.id.scr1); // 向添加ContentProviderA应用的数据 bt1.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { String eds1 = ed1.getText().toString(); String eds2 = ed2.getText().toString(); ContentValues content = new ContentValues(); if (!eds1.equals("") && !eds2.equals("")) { content.put(UserInfo.User.NAME, eds1); content.put(UserInfo.User.AGE, eds2); MainActivity.this.getContentResolver().insert( Uri.parse(UserInfo.User.uri), content); Toast.makeText(MainActivity.this, "数据插入成功", Toast.LENGTH_LONG).show(); // 刷新ListView界面 list1.setAdapter(adapter(0)); } else { Toast.makeText(MainActivity.this, "name和age不能为空", Toast.LENGTH_LONG).show(); } } }); // 根据条件删除ContentProviderA应用的数据 bt2.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { String eds1 = ed1.getText().toString(); String eds2 = ed2.getText().toString(); if (!eds1.equals("") || !eds2.equals("")) { HashMap<String, String[]> wheres = wheres(eds1, eds2); String sql = wheres.get("sql")[0]; String[] selectags = wheres.get("selectages"); MainActivity.this.getContentResolver().delete( Uri.parse(UserInfo.User.uri), sql, selectags); } else { Toast.makeText(MainActivity.this, "请输入删除条件", Toast.LENGTH_LONG).show(); } // 刷新ListView界面 list1.setAdapter(adapter(0)); } }); // 修改数据 bt3.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { String eds1 = ed1.getText().toString(); String eds2 = ed2.getText().toString(); ContentValues values = new ContentValues(); // 根据条件将列修改为xiong,23 values.put(UserInfo.User.NAME, "xiong"); values.put(UserInfo.User.AGE, "23"); if (!eds1.equals("") || !eds2.equals("")) { HashMap<String, String[]> wheres = wheres(eds1, eds2); String sql = wheres.get("sql")[0]; String[] selectags = wheres.get("selectages"); int i=MainActivity.this.getContentResolver().update( Uri.parse(UserInfo.User.uri), values, sql, selectags); } else { Toast.makeText(MainActivity.this, "请输入删除条件", Toast.LENGTH_LONG).show(); } // 刷新ListView界面 list1.setAdapter(adapter(0)); } }); // 根据条件查询ContentProviderA应用的数据 bt4.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (!ed1.getText().toString().equals("") || !ed2.getText().toString().equals("")) list1.setAdapter(adapter(1)); else list1.setAdapter(adapter(0)); } }); } // 用来判别条件 public HashMap<String, String[]> wheres(String eds1, String eds2) { HashMap<String, String[]> where = new HashMap<String, String[]>(); if (!eds1.equals("") && !eds2.equals("")) { String[] sql = { UserInfo.User.NAME + "=? and " + UserInfo.User.AGE + " =?" }; String[] selectages = { eds1, eds2 }; where.put("sql", sql); where.put("selectages", selectages); } if (!eds1.equals("") && eds2.equals("")) { String[] sql = { UserInfo.User.NAME + "=? " }; String[] selectages = { eds1 }; where.put("sql", sql); where.put("selectages", selectages); } if (eds1.equals("") && !eds2.equals("")) { String[] sql = { UserInfo.User.AGE + " =?" }; String[] selectages = { eds2 }; where.put("sql", sql); where.put("selectages", selectages); } return where; } // 用来显示数据 public SimpleAdapter adapter(int i) { Cursor cs = MainActivity.this.getContentResolver().query( Uri.parse(UserInfo.User.uriall), null, null, null, null); String eds1 = ed1.getText().toString(); String eds2 = ed2.getText().toString(); if (i == 1) { if (!eds1.equals("") || !eds2.equals("")) { HashMap<String, String[]> wheres = wheres(eds1, eds2); String sql = wheres.get("sql")[0]; String[] selectags = wheres.get("selectages"); cs = MainActivity.this.getContentResolver().query( Uri.parse(UserInfo.User.uri), null, sql, selectags, null); } } List<Map<String, Object>> lists = new ArrayList<Map<String, Object>>(); while (cs.moveToNext()) { Map<String, Object> map = new HashMap<String, Object>(); map.put("name", cs.getString(0)); map.put("age", cs.getString(1)); lists.add(map); } SimpleAdapter simepl = new SimpleAdapter(MainActivity.this, lists, R.layout.item, new String[] { "name", "age" }, new int[] { R.id.item_txt1, R.id.item_txt2 }); return simepl; } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }

activity.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity" > <ScrollView android:id="@+id/scr1" android:layout_width="match_parent" android:layout_height="wrap_content" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <Button android:id="@+id/bt1" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="添加" /> <Button android:id="@+id/bt2" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="删除" /> <Button android:id="@+id/bt3" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="更改" /> <Button android:id="@+id/bt4" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="查询" /> <EditText android:id="@+id/ed1" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="输入name条件进行增删改查" /> <EditText android:id="@+id/ed2" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="输age条件进行增删改查" /> </LinearLayout> </ScrollView> <ListView android:id="@+id/list" android:layout_width="match_parent" android:layout_height="wrap_content" > </ListView> </LinearLayout>

item.xml

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <TextView android:id="@+id/item_txt1" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <TextView android:id="@+id/item_txt2" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout>

监听ContentProvider数据改变
当程序A在执行insert、update、delete时,通过getContext().getContentResolver().notifyChange(uri, null)方法来告诉所有注册在该Uri的监听者数据发生改变

//删除数据 @Override public int delete(Uri uri, String selection, String[] selectionArgs) { int number = 0; if (uriMatcher.match(uri) == 1) { // 根据条件删除数据,并获取删除的行数 number = mysqlite.getReadableDatabase().delete("user_info", selection, selectionArgs); } // 通知数据已经改变 getContext().getContentResolver().notifyChange(uri, null); return number; }

在B程序通过registerContentObserver(Uri uri,boolean notifyForDescendents, ContentObserver observer)方法来监听A程序的数据改变

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 为uri的数据改变注册监听器 getContentResolver().registerContentObserver( Uri.parse("content://com.android.xiong.ConentProviderTestA.firstContentProvider/userinfo"), true, new SmsObserver(new Handler())); }

registerContentObserver中第三个参数为监听实例 ,需要通过继承ContentObserver类,并重写onChange(booleab selfChange)方法,该方法在监听Uri的ContentProvider的数据发生改变时触发该方法

// 提供方自定义的ContentOberver监听器 private final class Observer extends ContentObserver { public SmsObserver(Handler handler) { super(handler); } @Override public void onChange(boolean selfChange, Uri uri) { // 查询发送邮箱中的短息(处于正在发送状态的短信放在发送箱) Cursor cursor = getContentResolver().query( Uri.parse("content://com.android.xiong.ConentProviderTestA.firstContentProvider/userinfo"), null, null, null, null); } } }

时间: 2024-08-31 09:21:26

实例解析Android系统中的ContentProvider组件用法的相关文章

实例解析Android系统中的ContentProvider组件用法_Android

ContentProvider为Android四大组件之一,主要用来应用程序之间的数据共享,也就是说一个应用程序用ContentProvider将自己的数据暴露出来,其他应用程序通过ContentResolver来对其暴露出来的数据进行增删改查. ContenProvider与ContentResolver之间的对话同过Uri(通用资源标识符),一个不恰当的比喻就好像浏览器要显示一个网页要有一个东西发送请求,这相当于ContentResolver,你要拿东西就要知道去哪里拿,你就得知道服务器的域

深入解析Android系统中应用程序前后台切换的实现要点_Android

在介绍程序实现之前,我们先看下Android中Activities和Task的基础知识. 我们都知道,一个Activity 可以启动另一个Activity,即使这个Activity是定义在别一个应用程序里的,比如说,想要给用户展示一个地图的信息,现在已经有一个Activity可以做这件事情,那么现在你的Activity需要做的就是将请求信息放进一个Intent对象里,并且将这个Intent对象传递给startActivity(),那么地图就可显示出来了,但用户按下Back键之后,你的Activi

深入解析Android系统中应用程序前后台切换的实现要点

在介绍程序实现之前,我们先看下Android中Activities和Task的基础知识. 我们都知道,一个Activity 可以启动另一个Activity,即使这个Activity是定义在别一个应用程序里的,比如说,想要给用户展示一个地图的信息,现在已经有一个Activity可以做这件事情,那么现在你的Activity需要做的就是将请求信息放进一个Intent对象里,并且将这个Intent对象传递给startActivity(),那么地图就可显示出来了,但用户按下Back键之后,你的Activi

在Android系统中使用gzip进行数据传递实例代码_Android

接下来让我解说一下如何在Android系统中使用gzip进行数据传递 HTTP协议上的GZIP编码是一种用来改进WEB应用程序性能的技术.大流量的WEB站点常常使用GZIP压缩技术来减少文件大小减少文件大小有两个明显的好处一是可以减少存储空间二是通过网络传输文件时可以减少传输的时间.作者在写这篇博客时经过测试4.4MB的文本数据经过Gzip传输到客户端之后变为392KB压缩效率极高. 一.服务端 服务端有2种方式去压缩一种可以自己压缩但是更推荐第二种方式用PrintWriter作为输出流工具类代

Android零基础入门第2节:Android 系统架构和应用组件那些事

原文:Android零基础入门第2节:Android 系统架构和应用组件那些事  继上一期浅谈了Android的前世今生,这一期一起来大致回顾一下Android 系统架构和应用组件.   一.Android 系统架构 Android系统的底层建立在Linux系统之上,该平台由操作系统.中间件.用户界面和应用软件4层组成,它采用一种被称为软件叠层(Software Stack)的方式进行构建.这种软件叠层结构使得层与层之间相互分离,明确各层的分工.这种分工保证了层与层之间的低耦合,当下层的层内或层

Android系统中的进程管理:进程的创建

对于操作系统来说,进程管理是其最重要的职责之一. 考虑到这部分的内容较多,因此会拆分成几篇文章来讲解. 本文是进程管理系统文章的第一篇,会讲解Android系统中的进程创建. 本文适合Android平台的应用程序开发者,也适合对于Android系统内部实现感兴趣的读者. 概述 Android系统以Linux内核为基础,所以对于进程的管理自然离不开Linux本身提供的机制.例如: 通过fork来创建进行 通过信号量来管理进程 通过proc文件系统来查询和调整进程状态等 对于Android来说,进程

ios-iOS和Android系统中的微信分身版软件是如何实现的?

问题描述 iOS和Android系统中的微信分身版软件是如何实现的? 如题,微信同时只能启动一个实例,而分身版微信可以同时启动很多个实例,我想知道这是怎么做到的,其中原理是什么? 解决方案 觉得应该是从ART vm下手.猜测,是不是在精简一个小型vm来启动另一个APk. 解决方案二: Android平台上主要借助了系统的多账户机制,相当于在手机中建立了一个"虚拟机",就像是手机中的"第二系统",在其中运行的应用不会对原手机系统产生任何干扰,保障了两个账户的同时独立运

详细分析Android系统中定位服务的架构和实现

对于 Android 的应用开发人员来说,本文可以帮助他们了解他们所使用的 API 背后的实现.对于 Android 的系统开发人员来说,本文可以帮助他们更好的了解 Android 系统架构. 定位服务是移动设备上最常用的功能之一,下文以 Android 源码为基础,详细分析了 Android 系统中定位服务的架构和实现. 定位服务是 Android 系统提供的一项系统服务,在 Android 系统中,所有系统服务的架构都是类似的.只要明白其中一个,然后再去理解其他是很容易的. 对于 Andro

Android编程中selector背景选择器用法实例分析

本文实例讲述了Android编程中selector背景选择器用法.分享给大家供大家参考,具体如下: 在Android开发过程中,经常对某一View的背景在不同的状态下,设置不同的背景,增强用户体验.如果按钮,在按下时,背景变化,如果在代码中动态设置,相对比较麻烦.Android为我们提供了selector背景选择器可以非常方便的解决这一问题. Selector的结构描述: 1.android:state_pressed="true/false" true:表示按下状态下使用,false