android基础学习12——内容提供者ContentProvider的使用
来源:互联网 发布:淘宝店铺装修图片素材 编辑:程序博客网 时间:2024/05/20 21:18
内容提供者(ContentProvider)是Android系统四大组件之一,用于保存和检索数据,是Android系统中不同应用程序之间共享数据的接口。在Android系统中,应用程序之间是相互独立的,分别运行在自己的进程中,相互之间没有数据交换。若应用程序之间需要共享数据,就需要用到ContentProvider。ContentProvider是不同应用程序之间进行数据交换的标准API,它以Uri的形式对外提供数据,允许其他应用操作本应用数据。其他应用则使用ContentResolver,并根据ContentProvider提供的Uri操作指定数据。接下来通过一个案例“读取联系人信息”使用内容提供者暴露数据。该案例实现了查询自己暴露的数据,并将数据捆绑到ListView控件中的功能。
activity.xml
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/ll_root" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.lenovo.contentprovider.MainActivity"> <ListView android:id="@+id/lv" android:layout_width="match_parent" android:layout_height="match_parent"> </ListView></LinearLayout>
在layout文件夹下创建一个list_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="60dip" android:gravity="center_vertical" android:orientation="horizontal"> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5dip" android:src="@drawable/default_avatar"/> <LinearLayout android:layout_width="fill_parent" android:layout_height="60dip" android:layout_marginLeft="20dip" android:gravity="center_vertical" android:orientation="vertical"> <TextView android:id="@+id/tv_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5dip" android:text="姓名" android:textColor="#000000" android:textSize="18sp"/> <TextView android:id="@+id/tv_phone" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5dip" android:layout_marginTop="3dp" android:text="电话" android:textColor="#88000000" android:textSize="16sp" /> </LinearLayout></LinearLayout>
在drawble文件夹下添加一张名为default_avater的图片作为联系人的图片
创建数据库
package com.example.lenovo.contentprovider;import android.content.Context;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteOpenHelper;import android.util.Log;/** * Created by lenovo on 2017/6/8. */public class PersonSQLiteOpenHelper extends SQLiteOpenHelper { private static final String TAG="PersonSQLiteOpenHelper"; //数据库的构造方法,用来定义数据库的名称、数据库查询的结果集、数据库的版本 public PersonSQLiteOpenHelper(Context context){ super(context,"person.db",null,3); } //数据库第一次被创建的时候调用的方法 public void onCreate(SQLiteDatabase db){ //初始化数据库的表结构 db.execSQL("create table person(id integer primary key autoincrement,name varchar(20),number varchar(20))"); } //当数据库的版本号发生变化的时候(增加的时候)调用 public void onUpgrade(SQLiteDatabase db,int oldVersion,int newVersion){ Log.i(TAG,"数据库的版本变化了......"); }}创建Person类,用于封装id、name和number属性
package com.example.lenovo.contentprovider;/** * Created by lenovo on 2017/6/8. */public class Person { private int id; private String name; private String number; public Person() { } public String toString() { return "Person [id=" + id + ", name=" + name + ", number=" + number + "]"; } public Person(int id, String name, String number) { this.id = id; this.name = name; this.number = number; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getNumber() { return number; } public void setNumber(String number) { this.number = number; }}创建内容提供者
创建PersonDBProvider类继承ContentProvider,用于实现暴露数据库程序的功能
package com.example.lenovo.contentprovider;import android.content.ContentProvider;import android.content.ContentUris;import android.content.ContentValues;import android.content.UriMatcher;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;import android.net.Uri;/** * Created by lenovo on 2017/6/8. */public class PersonDBProvider extends ContentProvider { // 定义一个uri的匹配器 用于匹配uri 如果路径不满足条件 返回 -1 private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH); private static final int INSERT = 1; //添加数据匹配Uri路径成功时返回码 private static final int DELETE = 2; //删除数据匹配Uri路径成功时返回码 private static final int UPDATE = 3; //更改数据匹配Uri路径成功时返回码 private static final int QUERY = 4; //查询数据匹配Uri路径成功时返回码 private static final int QUERYONE = 5; //查询一条数据匹配Uri路径成功时返回码 //数据库操作类的对象 private PersonSQLiteOpenHelper helper; static { // 添加一组匹配规则. matcher.addURI("com.example.lenovo.db.personprovider", "insert", INSERT); matcher.addURI("com.example.lenovo.db.personprovider", "delete", DELETE); matcher.addURI("com.example.lenovo.db.personprovider", "update", UPDATE); matcher.addURI("com.example.lenovo.db.personprovider", "query", QUERY); //这里的“#”号为通配符凡是符合”query/”皆返回QUERYONE的返回码 matcher.addURI("com.example.lenovo.contentprovider.personprovider", "query/#", QUERYONE); } //当内容提供者被创建的时候 调用 适合 数据的初始化 public boolean onCreate() { helper = new PersonSQLiteOpenHelper(getContext()); return false; } //查询数据操作 public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { if (matcher.match(uri) == QUERY) { //匹配查询的Uri路径 //匹配成功 ,返回查询的结果集 SQLiteDatabase db = helper.getReadableDatabase(); //调用数据库操作的查询数据的方法 Cursor cursor = db.query("person", projection, selection, selectionArgs, null, null, sortOrder); return cursor; } else if (matcher.match(uri) == QUERYONE) { //匹配成功,根据id查询数据 long id = ContentUris.parseId(uri); SQLiteDatabase db = helper.getReadableDatabase(); Cursor cursor = db.query("person", projection, "id=?", new String[]{id+""}, null, null, sortOrder); return cursor; } else { throw new IllegalArgumentException("路径不匹配,不能执行查询操作"); } } //获取当前Uri的数据类型 public String getType(Uri uri) { if (matcher.match(uri) == QUERY) { // 返回查询的结果集 return "vnd.android.cursor.dir/person"; } else if (matcher.match(uri) == QUERYONE) { return "vnd.android.cursor.item/person"; } return null; } //添加数据 public Uri insert(Uri uri, ContentValues values) { if (matcher.match(uri) == INSERT) { //匹配成功 返回查询的结果集 SQLiteDatabase db = helper.getWritableDatabase(); db.insert("person", null, values); } else { throw new IllegalArgumentException("路径不匹配,不能执行插入操作"); } return null; } //删除数据 public int delete(Uri uri, String selection, String[] selectionArgs) { if (matcher.match(uri) == DELETE) { //匹配成功 返回查询的结果集 SQLiteDatabase db = helper.getWritableDatabase(); db.delete("person", selection, selectionArgs); } else { throw new IllegalArgumentException("路径不匹配,不能执行删除操作"); } return 0; } //更新数据 public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { if (matcher.match(uri) == UPDATE) { //匹配成功 返回查询的结果集 SQLiteDatabase db = helper.getWritableDatabase(); db.update("person", values, selection, selectionArgs); } else { throw new IllegalArgumentException("路径不匹配,不能执行修改操作"); } return 0; }}从上述代码中可以看出,在暴露数据的增、删、改、查方法之前,首先需要添加一组用于请求数据操作的Uri,然后在相应的增删改查方法中匹配Uri,匹配成功才能对数据进行操作。
创建数据库逻辑操作类
package com.example.lenovo.contentprovider;import android.content.ContentValues;import android.content.Context;import android.database.sqlite.SQLiteDatabase;/** * Created by lenovo on 2017/6/8. */public class PersonDao2 { private PersonSQLiteOpenHelper helper; //在构造方法里面完成helper的初始化 public PersonDao2(Context context){ helper=new PersonSQLiteOpenHelper(context); } //添加一条记录到数据库 public long add(String name,String number,int money){ SQLiteDatabase db=helper.getWritableDatabase(); ContentValues values=new ContentValues(); values.put("name",name); values.put("number",number); long id=db.insert("person",null,values); db.close(); return id; }}
MainActivity
package com.example.lenovo.contentprovider;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import java.util.ArrayList;import java.util.List;import java.util.Random;import android.content.ContentResolver;import android.database.Cursor;import android.net.Uri;import android.os.Handler;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ListView;import android.widget.TextView;public class MainActivity extends AppCompatActivity { private ListView lv; private List<Person> persons ; //创建一个Handler对象用于线程间通信 private Handler handler = new Handler(){ public void handleMessage(android.os.Message msg) { switch (msg.what) { case 100://接收到数据查询完毕的消息 //UI线程适配ListView lv.setAdapter(new MyAdapter()); break; } }; }; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); lv = (ListView) findViewById(R.id.lv); //由于添加数据、查询数据是比较耗时的,因此需要在子线程中做这两个操作 new Thread(){ public void run() { //添加数据 AddData(); //获取persons集合 getPersons(); //如果查询到数据 则向UI线程发送消息 if(persons.size() > 0){ handler.sendEmptyMessage(100); } }; }.start(); } //往person表中插入10条数据 public void AddData(){ PersonDao2 dao = new PersonDao2(this); long number = 885900000l; Random random = new Random(); for(int i=0;i<10;i++){ dao.add("wangwu"+i, Long.toString(number+i), random.nextInt(5000)); } } //利用ContentResolver对象查询本应用程序使用ContentProvider暴露的数据 private void getPersons() { //首先要获取查询的uri String url = "content://com.example.lenovo.db.personprovider/query"; Uri uri = Uri.parse(url); //获取ContentResolver对象 这个对象的使用后面会详细讲解 ContentResolver contentResolver = getContentResolver(); //利用ContentResolver对象查询数据得到一个Cursor对象 Cursor cursor = contentResolver.query(uri, null, null, null, null); persons = new ArrayList<Person>(); //如果cursor为空立即结束该方法 if(cursor == null){ return; } while(cursor.moveToNext()){ int id = cursor.getInt(cursor.getColumnIndex("id")); String name = cursor.getString(cursor.getColumnIndex("name")); String number = cursor.getString(cursor.getColumnIndex("number")); Person p = new Person(id, name, number); persons.add(p); } cursor.close(); } //适配器 private class MyAdapter extends BaseAdapter{ private static final String TAG = "MyAdapter"; // 控制listview里面总共有多个条目 public int getCount() { return persons.size(); //条目个数 == 集合的size } public Object getItem(int position) { return persons.get(position); } public long getItemId(int position) { return 0; } public View getView(int position, View convertView, ViewGroup parent) { //得到某个位置对应的person对象 Person person = persons.get(position); View view = View.inflate(MainActivity.this, R.layout.list_item, null); //一定要在view对象里面寻找孩子的id //姓名 TextView tv_name = (TextView) view.findViewById(R.id.tv_name); tv_name.setText("姓名:"+person.getName()); //电话 TextView tv_phone = (TextView) view.findViewById(R.id.tv_phone); tv_phone.setText("电话:"+person.getNumber()); return view; } }}上述代码使用ContentResolver查询本程序使用ContentProvider暴露的数据。
需要注意的是,当执行耗时操作时,应创建一个子线程将耗时操作放在子线程中,然后使用handler实现子线程与UI线程的通信。
在清单文件中注册PersonDBProvider
<provider android:authorities="com.example.lenovo.db.personprovider" android:name="com.example.lenovo.contentprovider.PersonDBProvider"> </provider>
运行程序能看到如图所示
阅读全文
0 0
- android基础学习12——内容提供者ContentProvider的使用
- 【Android基础】内容提供者ContentProvider的使用详解
- Android开发基础——内容提供者(ContentProvider)小结
- android ContentProvider(内容提供者)基础
- Android中内容提供者ContentProvider的使用
- Android 内容提供者ContentProvider的使用
- Android里内容提供者ContentProvider的使用
- Android——contentProvider内容提供者
- 内容提供者,ContentProvider的使用
- ContentProvider内容提供者的使用
- Android开发13——内容提供者ContentProvider的基本使用
- Android基础4(内容提供者ContentProvider)
- [Android Pro] 内容提供者ContentProvider的基本使用
- Android知识梳理之ContentProvider内容提供者的使用
- Android ContentProvider的基本使用1(内容提供者)
- Android学习之内容提供者ContentProvider
- Android学习九 ContentProvider内容提供者相关
- Android ContentProvider(内容提供者)
- 多种排序算法求中位数
- Python学习之旅-16
- Android6.0蓝牙开发中获取附近低功耗蓝牙设备结果权限问题分析
- 基于WebSocket的简易聊天室
- Android 简捷地为ListView添加上拉加载
- android基础学习12——内容提供者ContentProvider的使用
- Oracle number数据类型介绍
- Nodejs
- 超平面
- volatile(C# 参考)和Lock
- BeautifulSoup-爬虫实战
- 怎么做mysql数据库索引
- 操作系统(二):进程和线程管理_1_进程、线程
- 编程电子书大全