目录
1.Android 四大组件及纽带
- 活动:Activity
- 内容提供者:Content Provider
- 服务:Service
- 广播接收器:BroadcastReceiver
- 连接四大组件的纽带:Intent
2.内容提供者功能、原理、分类
- 功能1:存储和检索来自 数据源 的数据
- 功能2:使用 内容提供者 进行 跨应用 数据共享 (不同程序之间的桥梁)
- 原理:通过抽象底层数据源,将应用与数据层分离,:使数据源具有独立性
- 内容提供者分类:
- 自定义内容提供者
- 本机内容提供者
3.实现内容提供者
3.1 内容提供者实现步骤
- 自定义一个 ContentProvider 类
- 重写抽象方法: onCreate()、 insert()、 update()、 delete()、 query()、 getType()
- 在 AndroidManifest.xml 系统配置文件中注册 自定义内容提供者
- 指定要访问的内容的URI
- 在另一个应用里通过 ContentResolver 访问内容提供者公开的数据
3.2 系统配置文件注册内容提供者
<provider android:name="MyCustomProvider" android:authorities="com.DatabaseDemo.provider.MyCustomProvider"> </provider>
3.3 访问内容的 URI
- URI(Uniform Resource Identifier):统一资源标识符,是 URL 父级,包含 本地+网络 地址,URL只有网络地址
- 每个内容提供者公开一个 URI:唯一标识该内容提供者的数据集
- 如果一个内容提供者控制多个数据集,则需要为每个数据集指定单独的 URI
- 内容提供者的 URI 以字符串 content:// 开头,两种格式如下:
- 请求表中所有的值:content://bagname.contactprovider/Example
- 请求在特定位置可用的单个记录:content://bagname.contactprovider/Example/1
- 访问内容提供者,需要用 android.content 程序包的 UriMatcher 类
3.4 处理 MIME类型数据的请求
- 处理内容提供者提供的 MIME 类型数据的请求,需要重写 getType() 方法
- getType() 方法将 URI 对象作为参数,并返回字符串,该字符串唯一描述 URI 的 MIME 类型,返回类型:
- vnd.android.cursor.item/<contenttype>:对 单条目 返回 单项
- vnd.android.cursor.dir/<contenttype>:对 所有条目 返回 所有项
3.5 访问内容提供者公开数据
- 访问内容提供者公开的数据,需要使用 android.content.ContentResolver 类
- 每个 Android 应用上下文都包括一个可访问的 ContentResolver实例,如下:
- ContentResolver resolver = getContentResolver();
- 从内容提供者检索记录:ContentResolver.query() 方法 或 Activity.managedQuery() 方法
- 处理查询:必须在 ContentProvider 类扩展的类中实现 delete()、insert()、update() 和 query() 方法
4.应用内部使用内容提供者
- SQLHelper.java:
// SQLHelper.java public class SQLHelper extends SQLiteOpenHelper{ public SQLHelper(Context context) { super(context,"NIIT.db",null,1); Log.w("content:","初始化 SQLHelper类"); } @Override public void onCreate(SQLiteDatabase db) { // 数据库首次创建时调用 一般写创建表的代码 db.execSQL("create table Contacts(id integer primary key autoincrement, " + "name text, mobile text)"); db.execSQL("insert into Contacts(name,mobile) values('阿呆','88888888')"); db.execSQL("insert into Contacts(name,mobile) values('阿贝','66666666')"); Log.w("content:","SQLHelper类的 onCreate()方法被调用"); } @Override // 数据库升级时调用 执行添加、修改等操作 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { Log.w("content:","SQLHelper类的 onUpgrade()方法被调用"); }}
- MainActivity.java:
public class MainActivity extends Activity { Button b1, b2, b3, b4,selectAll; EditText etId, etName, etMobile; SQLHelper helper; SQLiteDatabase db; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); b1 = (Button) findViewById(R.id.insert); // 插入按钮 b2 = (Button) findViewById(R.id.modify); // 修改按钮 b3 = (Button) findViewById(R.id.delete); // 删除按钮 b4 = (Button) findViewById(R.id.query); // 查询按钮 selectAll = (Button) findViewById(R.id.selectAll); // 查询全部信息按钮 etId = (EditText) findViewById(R.id.etId); // id编辑视图 etName = (EditText) findViewById(R.id.etName);// 名字编辑视图 etMobile = (EditText) findViewById(R.id.etMobile);// 手机编辑视图 // 设置点击事件:以前是通过匿名内部类创建点击事件 现在用下面的自定义点击事件 ButtonListener listener = new ButtonListener(); b1.setOnClickListener(listener); b2.setOnClickListener(listener); b3.setOnClickListener(listener); b4.setOnClickListener(listener); selectAll.setOnClickListener(listener); helper = new SQLHelper(this); db = helper.getWritableDatabase(); } // 自定义点击事件 class ButtonListener implements OnClickListener { @Override public void onClick(View v) { switch (v.getId()) { case R.id.insert: // 获取两个参数:名字、手机,编号是自动增长的所以不需要获取,注意顺序问题! String[] args1={etName.getText().toString(),etMobile.getText().toString()}; // 自己书写sql语句 db.execSQL("insert into Contacts(name,mobile) values(?,?)",args1); Toast.makeText(MainActivity.this,"插入成功!",Toast.LENGTH_SHORT).show(); break; case R.id.modify: // 根据 id进行修改 需要获取id 注意顺序问题!不可以改变顺序 String[] args2={etName.getText().toString(),etMobile.getText().toString(), etId.getText().toString()}; db.execSQL("update Contacts set name=?,mobile=? where id=?",args2); Toast.makeText(MainActivity.this,"更新成功!",Toast.LENGTH_SHORT).show(); break; case R.id.delete: db.execSQL("delete from Contacts where id=?", new String[]{etId.getText().toString()}); Toast.makeText(MainActivity.this,"删除成功!",Toast.LENGTH_SHORT).show(); break; case R.id.query: Cursor c=db.rawQuery("select * from Contacts where id=?", new String[]{etId.getText().toString()}); if(c.moveToFirst()){ // 遍历查询 Cursor结果集 etName.setText(c.getString(1)); etMobile.setText(c.getString(2)); }else{ // 查询不到则为空 etName.setText(""); etMobile.setText(""); Toast.makeText(MainActivity.this,"查不到这个人!",Toast.LENGTH_SHORT).show(); } break; case R.id.selectAll: // 查询所有人 直接给表格 其他都是null Cursor cc = db.query("Contacts",null,null,null,null,null,null); StringBuffer sb=new StringBuffer(); // StringBuffer()遍历追加 while(cc.moveToNext()){ sb.append(cc.getInt(0)+"\t"+cc.getString(1)+"\t"+cc.getString(2)+"\n"); } Toast.makeText(MainActivity.this,sb,Toast.LENGTH_LONG).show(); }}}}
- ContactProvider.java:
public class ContactProvider extends ContentProvider{ // 重写 ContentProvider类里的方法 SQLHelper helper; SQLiteDatabase db; @Override public boolean onCreate() { // onCreate():初始化数据源信息 helper = new SQLHelper(this.getContext()); // 获取路径 this=ContentProvider db = helper.getWritableDatabase(); Log.w("content:","ContactProvider类 onCreate()方法被调用"); return true; } // query():实现数据查询(五个参数) // Uri:内容提供者地址 // projection:要查询的列,如:new String[]{"name","mobile"},查询name和mobile // selection:查询条件,如:where id=? // selectionArgs:查询条件的参数值,如:String[]{"1"}); 上述where条件参数值为1 // sortOrder:排序条件,如:name desc 表示名字降序排列 @Override public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { //返回一个 结果集Cursor Cursor c=db.query("Contacts",projection, selection, selectionArgs, null,null,sortOrder); Log.w("content:","ContactProvider类 query()方法被调用"); return c; } @Override public String getType(Uri uri) { // 处理内容提供者提供的 MIME 类型数据的请求,一般不用 Log.w("content:","ContactProvider类 getType()方法被调用"); return null; } // insert():插入数据(两个参数) // ContentValues:要插入的行对象 @Override public Uri insert(Uri uri, ContentValues values) { db.insert("Contacts",null,values); Log.w("content:","ContactProvider类 insert()方法被调用"); return null; } // delete():删除记录(三个参数) @Override public int delete(Uri uri, String selection, String[] selectionArgs) { int count = db.delete("Contacts",selection, selectionArgs); Log.w("content:","ContactProvider类 delete()方法被调用"); return count; // 返回值 表示删除时受到影响的行数 } //update():更新记录(四个参数) @Override public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { int count=db.update("Contacts",values, selection, selectionArgs); Log.w("content:","ContactProvider类 update()方法被调用"); return count; // 返回值 表示更新时受到影响的行数 }}
- activity_main.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"......> <TextView android:id="@+id/textView5"... android:text="联系人信息"/> <TextView // 编号提示信息 android:id="@+id/textView1"... android:text="编号"/> <EditText // 编号用户编辑区 android:id="@+id/etId".../> <TextView // 姓名提示信息 android:id="@+id/textView2"... android:text="姓名"/> <EditText // 姓名用户编辑区 android:id="@+id/etName".../> <TextView // 手机提示信息 android:id="@+id/textView3"... android:text="手机"/> <EditText // 手机用户编辑区 android:id="@+id/etMobile".../> <!-- 嵌套布局:添加四个按钮使之一行 --> <LinearLayout android:gravity="center_horizontal" > <Button android:id="@+id/insert" android:text="插入" /> <Button android:id="@+id/modify" android:text="修改" /> <Button android:id="@+id/delete" android:text="删除" /> <Button android:id="@+id/query" android:text="查询" /> </LinearLayout> <Button android:id="@+id/selectAll" // 查询所有大按钮 android:text="查看所有联系人" /> </LinearLayout>
- Andoid.Manifest.xml:
<provider // 注册内容提供者信息 // name:内容提供者的完整类名,即包名.类名,必须根据实际类名定义 android:name="com.Lyrelion.contentprovider.ContactProvider" // authorities:内容提供者的引用名/别名,可以自定义,但要唯一,最好以包名.类名格式写 android:authorities="com.Lyrelion.contentprovider.ContactProvider" // exported:是否要共享数据 android:exported="true" > </provider>
- 控制台部分效果展示:
- 应用界面效果展示:
5.跨应用使用内容提供者
- MainActivity.java:
public class MainActivity extends Activity { Button b1, b2, b3, b4; EditText etId, etName, etMobile; Uri uri=Uri.parse("content://com.Lyrelion.contentprovider.ContactProvider"); ContentResolver cr; // 内容解析器 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); b1 = (Button) findViewById(R.id.insert); // 插入按钮 b2 = (Button) findViewById(R.id.modify); // 修改按钮 etId = (EditText) findViewById(R.id.etId); // id编辑视图 ButtonListener listener = new ButtonListener(); b1.setOnClickListener(listener); // 内容解析器:Context类的 getContentResolver()方法创建 ontentResolver类 cr = this.getContentResolver();} class ButtonListener implements OnClickListener { @Override public void onClick(View v) { switch (v.getId()) { case R.id.insert: // 根据上面提供的Uri,查找到对应文件,执行插入 ContentValues newrow = new ContentValues(); // 创建一行 newrow.put("name",etName.getText().toString()); //设置 name列的值 newrow.put("mobile",etMobile.getText().toString()); //设置 mobile列的值 cr.insert(uri,newrow); // 把newrow 插入指定列 Toast.makeText(MainActivity.this,"插入成功!",Toast.LENGTH_LONG).show(); break; case R.id.modify: ContentValues uprow=new ContentValues(); uprow.put("name",etName.getText().toString()); uprow.put("mobile",etMobile.getText().toString()); cr.update(uri,uprow,"id=?",new String[]{etId.getText().toString()}); break; case R.id.delete: cr.delete(uri,"id=?",new String[]{etId.getText().toString()}); Toast.makeText(MainActivity.this,"删除成功!",Toast.LENGTH_LONG).show(); break; case R.id.query: Cursor c=cr.query(uri,null,"id=?", new String[]{etId.getText().toString()},null); if(c.moveToFirst()){ etName.setText(c.getString(1)); etMobile.setText(c.getString(2)); }else { etName.setText(""); etMobile.setText(""); Toast.makeText(MainActivity.this,"查询到了!",Toast.LENGTH_LONG).show();} break; }}}}
- 应用界面效果展示:
6.使用手机自身内容提供者
- MainActivity.java:
public class MainActivity extends Activity { Button b; TextView tv; ContentResolver cr; Uri uri=Phone.CONTENT_URI; //通过 iPhone类 常参CONTENT_URI 获取联系人内容提供者对应的地址 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); b=(Button)findViewById(R.id.button1); tv=(TextView)findViewById(R.id.textView1); cr=this.getContentResolver(); // 获取ContentResolver实例,内容解析器 b.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Cursor c=cr.query(uri, null,null,null,null); // 获取结果集 while(c.moveToNext()){ // 先获取指定列的索引 获取名字列的对应的索引值 int nameindex=c.getColumnIndex(Phone.DISPLAY_NAME); // 获取电话号码列对应的索引值 int numberindex=c.getColumnIndex(Phone.NUMBER); String name=c.getString(nameindex); //获取名字列的值 String number=c.getString(numberindex); //获取电话号码列的值 tv.append("\n姓名:"); tv.append(name); tv.append("\n电话:"); tv.append(number); tv.append("\n----------------------------------"); }}});}}
- activity_main.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <Button android:id="@+id/button1" android:text="显示联系人" /> <TextView // 可以使用 append()追加文本内容 android:id="@+id/textView1" android:text="联系人信息:" />
- Andoid.Manifest.xml:
<!--要使用手机自身的一些功能,需要获取对应的权限才可--> <uses-permission android:name="android.permission.READ_CONTACTS" />
- 应用界面效果展示:
7.内容提供者小结
- 内容提供者充当 应用间共享数据 的接口
- 所有内容提供者 使用公共接口 查询提供者 并返回结果,添加、更新和删除数据也从相同接口执行
- 要创建自己的内容提供者,需要创建 ContentProvider类 并重写其方法。
- 要访问内容提供者,可使用 ContentResolver类
- 创建内容提供者后,必须将其添加到 系统配置文件(AndroidManifest.xml)
Android课堂笔记(五)——内容提供者
猜你喜欢
转载自blog.csdn.net/Lyrelion/article/details/105066814
今日推荐
周排行