实例讲解Android中ContentProvider组件的使用方法

 更新时间:2016年04月21日 16:05:49   作者:summerpxy  
这篇文章主要介绍了Android中ContentProvider组件的使用方法,包括ContentProvider使用单元测试的步骤,需要的朋友可以参考下

ContentProvider基本使用
为了在应用程序之间交换数据,android提供了ContentProvider,ContentProvider是不同应用程序之间进行数据交换的标准API,当一个应用程序需要把自己的数据暴露给其他程序使用时,该应用程序就可以通过提供ContentPRovider来实现,其他应用程序就可以通过ContentResolver来操作ContentProvider暴露的数据。

实现ContentProvider的步骤:

1)编写一个类,继承ContentProvider,并且重写里面的CRUD方法。

2)在androidmanifest.xml文件中注册provider。

在androidmanifest.xml中注册provider需要以下3个属性:

             android:name              provider的实现类。

             android:authorities       provider的uri。

             android:exported          provider是否暴露给其他程序。


ContentResovler操作ContentProvider:

1)获取ContentResolver,getContentResovler()方法来自于ContextWrapper,所以activity和service中都可以使用。

2)调用CURD方法,通过参数url,调用指定的ContentProvider的方法。


下面是一个demo,向contentProvider中插入一条数据,并且返回到listview中。

main.xml:

<RelativeLayout 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"
  tools:context=".Main" >
 
  <ListView
    android:id="@+id/listview"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />
 
</RelativeLayout>

MySQLiteOpenHelper类

package com.app.dao;
 
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
 
public class MySQLiteOpenHelper extends SQLiteOpenHelper {
 
  public MySQLiteOpenHelper(Context context, String name,
      CursorFactory factory, int version) {
    super(context, name, factory, version);
 
  }
 
  @Override
  public void onCreate(SQLiteDatabase db) {
 
    String create_sql = "create table tb_test(_id integer primary key autoincrement,name,gender,age)";
     
    db.execSQL(create_sql);
  }
 
  @Override
  public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
 
  }
 
}

MyContentProvider类

package com.app.dao;
 
import android.content.ContentProvider;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
 
public class MyContentProvider extends ContentProvider{
 
  MySQLiteOpenHelper helper=null;
  @Override
  public int delete(Uri arg0, String arg1, String[] arg2) {
     
    return 0;
  }
 
  @Override
  public String getType(Uri arg0) {
    // TODO Auto-generated method stub
    return null;
  }
 
  @Override
  public Uri insert(Uri arg0, ContentValues values) {
     
    String insert_sql="insert into tb_test values(null,'wx','boy',17)";
     
    helper.getReadableDatabase().execSQL(insert_sql);
     
    return null;
  }
 
  @Override
  public boolean onCreate() {
     
    helper=new MySQLiteOpenHelper(this.getContext(),"test.db3",null,1);
     
    return true;
  }
 
  @Override
  public Cursor query(Uri arg0, String[] arg1, String arg2, String[] arg3,
      String arg4) {
     
    String query_sql="select * from tb_test";
     
    Cursor cursor=helper.getReadableDatabase().rawQuery(query_sql, null);
     
    return cursor;
  }
 
  @Override
  public int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3) {
    // TODO Auto-generated method stub
    return 0;
  }
 
}

listview的显示界面show.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/name"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />
 
  <TextView
    android:id="@+id/gender"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="60dp" />
 
  <TextView
    android:id="@+id/age"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="60dp" />
 
</LinearLayout>

Main.java

package com.app.main;
 
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.widget.CursorAdapter;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
 
public class Main extends Activity {
 
  ContentResolver resolver = null;
 
  ListView lv = null;
 
  @SuppressLint("NewApi")
  @Override
  protected void onCreate(Bundle savedInstanceState) {
 
    super.onCreate(savedInstanceState);
 
    setContentView(R.layout.main);
 
    lv = (ListView) this.findViewById(R.id.listview);
 
    resolver = this.getContentResolver();
 
    String str = "content://com.app.test.db/";
 
    Uri uri = Uri.parse(str);
 
    resolver.insert(uri, null);
 
    Cursor cursor = resolver.query(uri, null, null, null, null);
 
    SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
        R.layout.show, cursor,
        new String[] { "name", "gender", "age" }, new int[] {
            R.id.name, R.id.gender, R.id.age },
        CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
 
    lv.setAdapter(adapter);
 
  }
 
}

实现效果:(执行了3次插入后的效果)

2016421160202125.png (720×1280)

ContentProvider的单元测试
ContentProvider是android的四大组件之一,在编写代码的时候最好是加上单元测试,这样可以确定对数据的CRUD的正确。本篇文章主要介绍ContentProvider中两个主要辅助类的使用还有单元测试的在ContentProvider中的使用。

需要用到的两个辅助类:UriMatcher类和ContentUris类。

UriMatcher类:能够对输入的uri参数就行匹配,以确定对什么表执行什么样的操作。

ContentUris类:有些方法需要返回uri,运用此类可以方便的生成uri类。

对于单元测试,个人觉得非常有必要在今后写代码的时候使用,这样可以非常准确的确定代码的正确性。

使用单元测试的步骤:

 1)加入instrumentation,这个部分的代码是固定,也可以完全在ADT提供的向导中导入。

<instrumentation
    android:name="android.test.InstrumentationTestRunner"
    android:targetPackage="com.example.android_contentprovider" >
  </instrumentation>

2)添加<uses-library>,这个部分的代码也是固定的写法。

 <uses-library android:name="android.test.runner" />


好了,必备的知识已经讲完了,现在上代码:

1)生成一个SQLiteDatabase类,这个是必需的类MySQLiteOpenHelper类

package com.app.db;
 
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
 
public class MySQLiteOpenHelper extends SQLiteOpenHelper {
 
  private static String DB_NAME = "test.db3";
  private static int VERSION = 1;
 
  public MySQLiteOpenHelper(Context context) {
    super(context, DB_NAME, null, VERSION);
 
  }
 
  @Override
  public void onCreate(SQLiteDatabase db) {
       //建表语句
    String create_student = "create table student(_id integer primary key autoincrement,name varchar(10),age integer,gender vachar(10))";
     
    db.execSQL(create_student);
       //千万不能执行这句  // db.close();
 
  }
 
  @Override
  public void onUpgrade(SQLiteDatabase arg0, int arg1, int arg2) {
 
  }
 
}

 
然后添加我们需要的MyContentProvider类:

package com.app.contentprovider;
 
import com.app.db.MySQLiteOpenHelper;
 
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;
import android.util.Log;
 
public class MyContentProvider extends ContentProvider {
 
  MySQLiteOpenHelper helper = null;
 
  private static UriMatcher matcher = new UriMatcher(UriMatcher.NO_MATCH);
 
  // 匹配单条记录
  private static final int student = 1;
  // 匹配多条记录
  private static final int students = 2;
 
  static {
    matcher.addURI("com.app.wx", "student/#", student);
 
    matcher.addURI("com.app.wx", "student", students);
  }
 
  @Override
  public int delete(Uri uri, String selection, String[] selectionArgs) {
 
    SQLiteDatabase db = helper.getWritableDatabase();
 
    int action = matcher.match(uri);
 
    switch (action) {
     
    // 匹配单条记录
    case student:
 
      long id = ContentUris.parseId(uri);
     //获取单条记录的id号
      String delete_id = "_id=" + id;
 
      if (selection != null) {
        delete_id += delete_id + " and " + selection;
      }
 
      db.delete("student", delete_id, selectionArgs);
 
      break;
       
    // 匹配多条记录
    case students:
 
      db.delete("student", selection, selectionArgs);
 
      break;
    }
     
    return 0;
  }
 
  //必需实现这个方法,这个方法与intent有关系,以后再讲
  @Override
  public String getType(Uri uri) {
 
    int code = matcher.match(uri);
    switch (code) {
    case student:
      return "vnd.android.cursor.item/student_item";
    case students:
      return "vnd.android.cursor.dir/students";
    default:
      return null;
    }
  }
 
  @Override
  public Uri insert(Uri uri, ContentValues values) {
 
    SQLiteDatabase db = helper.getWritableDatabase();
 
    int action = matcher.match(uri);
 
    switch (action) {
 
    case students:
 
      long id1 = db.insert("student", "_id", values);
 
      Log.i("--------", ContentUris.withAppendedId(uri, id1).toString());
 
      return ContentUris.withAppendedId(uri, id1);
 
    }
 
    return null;
  }
 
  @Override
  public boolean onCreate() {
 
    helper = new MySQLiteOpenHelper(this.getContext());
 
    return true;
  }
 
  @Override
  public Cursor query(Uri uri, String[] projection, String selection,
      String[] selectionArgs, String orderBy) {
 
    SQLiteDatabase db = helper.getWritableDatabase();
 
    Cursor cursor = null;
 
    int action = matcher.match(uri);
 
    switch (action) {
 
    case students:
 
      cursor = db.query("student", projection, selection, selectionArgs,
          null, null, orderBy);
 
      break;
 
    }
 
    System.out.println("-----------count:" + cursor.getCount());
 
    return cursor;
  }
 
  @Override
  public int update(Uri uri, ContentValues values, String selection,
      String[] arg3) {
 
    int count = -1;
 
    SQLiteDatabase db = helper.getWritableDatabase();
 
    int action = matcher.match(uri);
 
    switch (action) {
 
    case student:
      // 以id来处理更新
      long id = ContentUris.parseId(uri);
 
      String id_selection = "_id=" + id;
 
      if (selection != null && !selection.equals("")) {
 
        id_selection = id_selection + " and " + values;
 
      }
 
      count = db.update("student", values, id_selection, arg3);
 
      System.out.println("----------count:" + count);
 
      break;
    }
 
    return count;
  }
 
}

这个类很长,但是执行的方法都是比较常见的CURD的方法,重要的是UriMatcher和ContentUris类的使用。

接着执行单元测试类:Test

package com.app.contentprovider;
 
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.test.AndroidTestCase;
import android.util.Log;
 
public class Test extends AndroidTestCase {
 
  public void insert() {
 
    ContentResolver resolver = this.getContext().getContentResolver();
 
    String str = "content://com.app.wx/student";
 
    ContentValues values = new ContentValues();
 
    values.put("name", "wzq");
 
    values.put("age", 18);
 
    values.put("gender", "boy");
 
    resolver.insert(Uri.parse(str), values);
 
  }
 
  public void update() {
 
    ContentResolver resolver = this.getContext().getContentResolver();
 
    String str = "content://com.app.wx/student/2";
 
    ContentValues values = new ContentValues();
 
    values.put("name", "哈哈");
 
    resolver.update(Uri.parse(str), values, null, null);
 
  }
 
  public void query() {
 
    ContentResolver resolver = this.getContext().getContentResolver();
 
    String str = "content://com.app.wx/student";
 
    Uri uri = Uri.parse(str);
 
    Cursor cursor = resolver.query(uri, new String[] { "_id",
        "name,age,gender" }, null, null, "_id desc");
 
    Log.d("------count",cursor.getCount()+"");
  }
 
  public void delete() {
    ContentResolver resolver = this.getContext().getContentResolver();
 
    String str = "content://com.app.wx/student/2";
 
    Uri uri = Uri.parse(str);
 
    long id=resolver.delete(uri, null, null);
 
  }
 
}

执行insert方法之后(执行了三次):

2016421160332881.png (463×93)

执行了update方法之后:

2016421160354111.png (458×101)

执行了query方法之后:

2016421160411590.png (617×92)

执行了delete方法之后:

2016421160429449.png (513×79)

相关文章

  • Templates实战之更优雅实现自定义View构造方法详解

    Templates实战之更优雅实现自定义View构造方法详解

    本篇文章介绍如何利用Android Studio提供的Live Templates更优雅实现自定义View的构造方法,说句人话就是:简化自定义View构造参数模板代码的编写,实现自动生成,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • Android实现文字滚动播放效果的代码

    Android实现文字滚动播放效果的代码

    这篇文章主要介绍了Android实现文字滚动播放效果,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-07-07
  • Android实现接近传感器

    Android实现接近传感器

    这篇文章主要为大家详细介绍了Android实现接近传感器,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-04-04
  • 如何在android中制作一个方向轮盘详解

    如何在android中制作一个方向轮盘详解

    这篇文章主要给大家介绍了关于如何在android中制作一个方向轮盘的相关资料,这个是在手游领域中很常见的用于控制方向的轮盘,文中通过示例代码介绍的非常详细,需要的朋友可以参考下
    2021-09-09
  • Android自定义控件仿QQ抽屉效果

    Android自定义控件仿QQ抽屉效果

    这篇文章主要为大家详细介绍了Android自定义控件仿QQ抽屉效果的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-03-03
  • Android开发之基于DialogFragment创建对话框的方法示例

    Android开发之基于DialogFragment创建对话框的方法示例

    这篇文章主要介绍了Android开发之基于DialogFragment创建对话框的方法,结合实例形式分析了DialogFragment创建对话框的具体功能与布局相关实现技巧,需要的朋友可以参考下
    2017-08-08
  • Android自定义一个图形单点移动缩小的效果

    Android自定义一个图形单点移动缩小的效果

    本文通过实例代码给大家介绍了android 自定义图形单点移动缩小效果,代码简单易懂,非常不错,具有参考借鉴价值,需要的的朋友参考下吧
    2017-08-08
  • Android实现京东秒杀界面

    Android实现京东秒杀界面

    这篇文章主要为大家详细介绍了Android实现京东秒杀界面,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-04-04
  • Flutter 中的PageStorage小部件使用及最佳实践

    Flutter 中的PageStorage小部件使用及最佳实践

    在Flutter中,PageStorage小部件提供了一种方法来保存和恢复页面间的信息,这对于具有多个页面且需要在这些页面之间共享状态的应用程序非常有用,本文将详细介绍PageStorage的用途、如何使用它以及一些最佳实践,感兴趣的朋友跟随小编一起看看吧
    2024-05-05
  • Handler实现倒计时功能

    Handler实现倒计时功能

    这篇文章主要为大家详细介绍了Handler实现倒计时功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-04-04

最新评论