原创 Android之自定义 ContentProvider

2021-9-2 15:01 2044 10 10 分类: 软件与OS 文集: android studio

在学习了ContentProvider 的几个常用类和如何创建一个内容提供者的方法之后,下面我们用一个实例来进一步加深理解。通过一个完整的实例来展示如何ContentProvider进行数据库操作。将通过创建 100条模拟数据,用ListView 展示出来

在进行具体的数据库操作之前,先建立一个Java 实体类 User类,再通过这个实体类进行数据的封装。User类中包括 userIdnameage三个属性,具体代码如下

  1. package com.rfstar.sqlitetest2;
  2. public class User {
  3. private int userId;
  4. private String name;
  5. private int age;
  6. public int getUserId()
  7. {
  8. return userId;
  9. }
  10. public void setUserId(int userId)
  11. {
  12. this.userId=userId;
  13. }
  14. public String getName()
  15. {
  16. return name;
  17. }
  18. public void setName(String name)
  19. {
  20. this.name=name;
  21. }
  22. public int getAge()
  23. {
  24. return age;
  25. }
  26. public void setAge(int age)
  27. {
  28. this.age=age;
  29. }
  30. }

完成Java实体类的创建之后,通过继承SQLiteOpenHelper实现数据库辅助类,实现其中onCeate()法和onUpgrate()方法onCreate()方法中创建表并使段与User类的属性相一致。同时实现onUpgrate()方法,以更新数据库。

  1. package com.rfstar.sqlitetest2;
  2. import android.content.Context;
  3. import android.database.sqlite.SQLiteDatabase;
  4. import android.database.sqlite.SQLiteOpenHelper;
  5. public class OpenHelper extends SQLiteOpenHelper {
  6. private static final String name="test.db";
  7. private static final int version=1;
  8. public OpenHelper(Context context)
  9. {
  10. super(context,name,null,version);
  11. }
  12. @Override
  13. public void onCreate(SQLiteDatabase sqLiteDatabase) {
  14. sqLiteDatabase.execSQL("CREATE TABLE IF NOT EXISTS "+
  15. "user (person_id INTEGER PRIMARY KEY AUTOINCREMENT,"+
  16. "name varchar(32),age INTEGER)");
  17. }
  18. @Override
  19. public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
  20. if(newVersion>oldVersion)
  21. {
  22. sqLiteDatabase.execSQL("ALTER TABLE user ADD phone VARCHAR(11)");
  23. }
  24. }
  25. }

接下来创建UserDao类,并在该类中实现对User的增、删、改、查操作,代码如下:

  1. package com.rfstar.sqlitetest2;
  2. import android.content.ContentValues;
  3. import android.content.Context;
  4. import android.database.Cursor;
  5. import android.database.sqlite.SQLiteDatabase;
  6. import java.util.ArrayList;
  7. import java.util.List;
  8. public class UserDao {
  9. private SQLiteDatabase database;
  10. public UserDao(SQLiteDatabase sqLiteDatabase) {
  11. this.database = sqLiteDatabase;
  12. }
  13. public boolean insert(User user) {
  14. ContentValues contentValues = new ContentValues();
  15. contentValues.put("name", user.getName());
  16. contentValues.put("age", user.getAge());
  17. long insertResult = database.insert("user", null, contentValues);
  18. if (insertResult == -1) {
  19. return false;
  20. }
  21. return true;
  22. }
  23. public boolean delete(User user) {
  24. int deleteResult = database.delete("user", "user_id+?", new String[]{user.getUserId() + ""});
  25. if (deleteResult == 0){
  26. return false;
  27. }
  28. return true;
  29. }
  30. public boolean update(User user)
  31. {
  32. ContentValues contentValues=new ContentValues();
  33. contentValues.put("name",user.getName());
  34. contentValues.put("age",user.getAge());
  35. int updateResult=database.update("user",contentValues,"user_id=?",new String[]{user.getUserId()+""});
  36. if(updateResult==0)
  37. {
  38. return false;
  39. }
  40. return true;
  41. }
  42. public User queryOne(User user)
  43. {
  44. Cursor cursor=database.query("user",null,"name=?",new String[]
  45. {user.getName()},null,null,null);
  46. while (cursor.moveToNext())
  47. {
  48. user.setUserId(cursor.getInt(0));
  49. user.setAge(cursor.getInt(2));
  50. }
  51. return user;
  52. }
  53. public List<User> queryAll()
  54. {
  55. List<User> userList=new ArrayList<>();
  56. Cursor cursor=database.query("user",null,null,null,null,null,null);
  57. while (cursor.moveToNext())
  58. {
  59. User user=new User();
  60. user.setUserId(cursor.getInt(0));
  61. user.setName(cursor.getString(1));
  62. user.setAge(cursor.getInt(2));
  63. userList.add(user);
  64. }
  65. return userList;
  66. }
  67. }

当完成上述3个类之后,接下来就可以使用Activity进行各项操作了(1)创建数据

创建一个MainActivity,并在MainActivity中创建一个循环生成100条数据的方法,代码如下:

  1. package com.rfstar.sqlitetest2;
  2. import androidx.appcompat.app.AppCompatActivity;
  3. import android.database.sqlite.SQLiteDatabase;
  4. import android.os.Bundle;
  5. import android.util.Log;
  6. import android.widget.ListView;
  7. import android.widget.SimpleAdapter;
  8. import java.util.ArrayList;
  9. import java.util.HashMap;
  10. import java.util.List;
  11. import java.util.Map;
  12. public class MainActivity extends AppCompatActivity {
  13. private OpenHelper openHelper;
  14. @Override
  15. protected void onCreate(Bundle savedInstanceState) {
  16. super.onCreate(savedInstanceState);
  17. setContentView(R.layout.activity_main);
  18. openHelper=new OpenHelper(this);
  19. initData();
  20. }
  21. private void initData()
  22. {
  23. SQLiteDatabase sqLiteDatabase=openHelper.getReadableDatabase();
  24. UserDao userDao=new UserDao(sqLiteDatabase);
  25. sqLiteDatabase.beginTransaction();
  26. try
  27. {
  28. User user=new User();
  29. for(int i=0;i<100;i++)
  30. {
  31. user.setName("大鸟科创空间"+i);
  32. user.setAge(6);
  33. userDao.insert(user);
  34. }
  35. sqLiteDatabase.setTransactionSuccessful();
  36. }catch (Exception e)
  37. {
  38. Log.e("user Transaction",e.toString());
  39. }finally {
  40. sqLiteDatabase.endTransaction();
  41. sqLiteDatabase.close();
  42. }
  43. }
  44. }

我们在这个应用中增加一个ContentProvider,再创建一个新的应用,在应用中去操作这个ContentProvider的数据。

  首先创建UserProvider类,并让UserProvider类继承ContentProvider类,并实现onCreate()等方法。这些方法主要是对数据库进行操作,代码如下:

  1. package com.rfstar.sqlitetest;
  2. import android.content.ContentProvider;
  3. import android.content.ContentUris;
  4. import android.content.ContentValues;
  5. import android.content.UriMatcher;
  6. import android.database.Cursor;
  7. import android.database.sqlite.SQLiteDatabase;
  8. import android.net.Uri;
  9. import java.util.regex.Matcher;
  10. public class UserProvider extends ContentProvider {
  11. private OpenHelper openHelper;
  12. //若不匹配采用UriMatcher.NO_MATCH(-1)返回
  13. private static final UriMatcher MATCHER=new UriMatcher(UriMatcher.NO_MATCH);
  14. //匹配码
  15. private static final int USER=1;
  16. private static final int USER_ID=2;
  17. static
  18. {
  19. //匹配返回USER,不匹配返回-1
  20. MATCHER.addURI("com.rfstar.sqlitetest.userProvider","user",USER);
  21. //匹配返回USER_ID,不匹配返回-1
  22. MATCHER.addURI("com.rfstar.sqlitetest.userProvider","user/#",USER_ID);
  23. }
  24. @Override
  25. public boolean onCreate()
  26. {
  27. openHelper=new OpenHelper(this.getContext());
  28. return true;
  29. }
  30. /**
  31. * 外部应用向本应用插入数据
  32. */
  33. @Override
  34. public Uri insert(Uri uri, ContentValues values)
  35. {
  36. SQLiteDatabase db=openHelper.getWritableDatabase();
  37. switch (MATCHER.match(uri))
  38. {
  39. case USER:
  40. long id=db.insert("user","name",values);
  41. Uri insertUri= ContentUris.withAppendedId(uri,id);
  42. return insertUri;
  43. default:
  44. throw new IllegalArgumentException("this is unknown uri:"+uri);
  45. }
  46. }
  47. /**
  48. * 外部应用向本应用删除数据
  49. */
  50. @Override
  51. public int delete(Uri uri,String selection,String[] selectionArgs)
  52. {
  53. SQLiteDatabase db=openHelper.getWritableDatabase();
  54. switch (MATCHER.match(uri))
  55. {
  56. case USER:
  57. return db.delete("user",selection,selectionArgs);//删除所有记录
  58. case USER_ID:
  59. long id=ContentUris.parseId(uri);//取得跟在Uri后面的数字
  60. String where="user_id="+id;
  61. if(null!=selection&&!"".equals(selection.trim()))
  62. {
  63. where+="and"+selection;
  64. }
  65. return db.delete("user",where,selectionArgs);
  66. default:
  67. throw new IllegalArgumentException("this is unknown uri:"+uri);
  68. }
  69. }
  70. /**
  71. * 外部应用向本应用更新数据
  72. */
  73. @Override
  74. public int update(Uri uri,ContentValues values,String selection,String[] selectionArgs)
  75. {
  76. SQLiteDatabase db=openHelper.getWritableDatabase();
  77. switch (MATCHER.match(uri))
  78. {
  79. case USER:
  80. return db.update("user",values,selection,selectionArgs);//更新所有记录
  81. case USER_ID:
  82. long id=ContentUris.parseId(uri);//取得跟在Uri后面的数字
  83. String where="user_id="+id;
  84. if(null!=selection&&!"".equals(selection.trim()))
  85. {
  86. where+="and"+selection;
  87. }
  88. return db.update("user",values,where,selectionArgs);
  89. default:
  90. throw new IllegalArgumentException("this is unknown uri:"+uri);
  91. }
  92. }
  93. /**
  94. * 如果是单条记录,应该返回以vnd.android.cursor.item/为首的字符串
  95. * 如果是多条记录,应该返回以vnd.android.cursor.dir/为首的字符串
  96. */
  97. @Override
  98. public String getType(Uri uri)
  99. {
  100. switch(MATCHER.match(uri))
  101. {
  102. case USER:
  103. return "vnd.android.cursor.dir/user";
  104. case USER_ID:
  105. return "vnd.android.cursor.item/user";
  106. default:
  107. throw new IllegalArgumentException("this is unknown uri:"+uri);
  108. }
  109. }
  110. @Override
  111. public Cursor query(Uri uri,String[] projection,String selection,String[]selectionArgs,String sortOrder)
  112. {
  113. SQLiteDatabase db=openHelper.getReadableDatabase();
  114. switch (MATCHER.match(uri))
  115. {
  116. case USER:
  117. return db.query("user",projection,selection,selectionArgs,null,null,sortOrder);
  118. case USER_ID:
  119. long id=ContentUris.parseId(uri);
  120. String where="user_id="+id;
  121. if(null!=selection&&!"".equals(selection.trim()))
  122. {
  123. where+="and"+selection;
  124. }
  125. return db.query("user",projection,where,selectionArgs,null,null,sortOrder);
  126. default:
  127. throw new IllegalArgumentException("this is unknown uri:"+uri);
  128. }
  129. }
  130. }

代码编写完成后,需要在AndroidManifest.xml文件中进行配置。在Application节点下面增加一条配置:

  1. <provider
  2. android:name="com.rfstar.sqlitetest.UserProvider"
  3. android:authorities="com.rfstar.sqlitetest.userProvider"
  4. android:exported="true"
  5. android:multiprocess="true"/>

此时运行应用在手机上,100条数据就创建成功了。但是,此时它已经不是一个简单的应用了,而是变成了一个内容提供者。

  创建一个新的应用,在此类中使用ContentResolver来获取ContentProvider中的数据,并通过ListView展示出来。

(2)展示数据

在上一部分创建了100条数据的基础上,用ListView来展现这些数据。这需要修改Acticity的布局文件,并创建一个item布局文件,同时在Activity中查询数据。由于数据中只有name age两个文本,因此选择 SimpleAdapter 作为 ListView 的适配器。

在布局文件中加入一个ListView控件:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:app="http://schemas.android.com/apk/res-auto"
  4. xmlns:tools="http://schemas.android.com/tools"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent"
  7. tools:context=".MainActivity">
  8. <ListView
  9. android:id="@+id/user_list"
  10. android:layout_width="match_parent"
  11. android:layout_height="wrap_content"/>
  12. </RelativeLayout>

为了能够展示出数据中的name和age两个字段,我们创建一个item:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent">
  5. <TextView
  6. android:id="@+id/user_name"
  7. android:layout_width="0dp"
  8. android:layout_height="match_parent"
  9. android:layout_weight="1"
  10. android:layout_gravity="center"
  11. android:textSize="20dp"/>
  12. <TextView
  13. android:id="@+id/user_age"
  14. android:layout_width="0dp"
  15. android:layout_height="match_parent"
  16. android:layout_weight="1"
  17. android:gravity="center_vertical"
  18. android:textSize="20dp"/>
  19. </LinearLayout>

完成了这几个步骤之后,就可以在MainActivity中查询数据库并使用适配器展示到ListView中了。此时使用ContentResolver来获取ContentProvider中的数据:

  1. package com.rfstar.sqlitetest31;
  2. import androidx.appcompat.app.AppCompatActivity;
  3. import android.database.sqlite.SQLiteDatabase;
  4. import android.os.Bundle;
  5. import android.widget.ListView;
  6. import android.widget.SimpleAdapter;
  7. import java.util.ArrayList;
  8. import java.util.HashMap;
  9. import java.util.List;
  10. import java.util.Map;
  11. public class MainActivity extends AppCompatActivity {
  12. private ListView listView;
  13. private List<Map<String,Object>> mapList;
  14. private OpenHelper openHelper;
  15. private List<User> userList;
  16. private UserResolve userResolve;
  17. @Override
  18. protected void onCreate(Bundle savedInstanceState) {
  19. super.onCreate(savedInstanceState);
  20. setContentView(R.layout.activity_main);
  21. initData();
  22. initView();
  23. }
  24. private void initView()
  25. {
  26. listView=(ListView)findViewById(R.id.user_list);
  27. final SimpleAdapter simpleAdapter=new SimpleAdapter(
  28. this,mapList,R.layout.item,
  29. new String[]{"name","age"},new int[]{R.id.user_name,R.id.user_age});
  30. listView.setAdapter(simpleAdapter);
  31. }
  32. private void initData() {
  33. userResolve=new UserResolve(this);
  34. userList=userResolve.query();
  35. mapList=new ArrayList<>();
  36. for(User user:userList)
  37. {
  38. Map<String,Object> map=new HashMap<>();
  39. map.put("name",user.getName());
  40. map.put("age",user.getAge());
  41. mapList.add(map);
  42. }
  43. }
  44. }

运行程序,就会发现创建数据时添加的100条数据显示在界面上了,效果如下图所示:

             ContentResolve应用中的数据

作者: 大鸟科创空间, 来源:面包板社区

链接: https://mbb.eet-china.com/blog/uid-me-3949041.html

版权声明:本文为博主原创,未经本人允许,禁止转载!

文章评论0条评论)

登录后参与讨论
我要评论
0
10
关闭 站长推荐上一条 /2 下一条