Heim  >  Artikel  >  Java  >  Zusammenfassung und ausführliche Erklärung basierend auf Android ContentProvider

Zusammenfassung und ausführliche Erklärung basierend auf Android ContentProvider

高洛峰
高洛峰Original
2017-02-07 15:59:21981Durchsuche

1. Anwendbare Szenarien
1) ContentProvider bietet eine einheitliche Schnittstelle zum Speichern und Lesen von Daten
2) Mithilfe von ContentProvider können Anwendungen den Datenaustausch erreichen
3) Viele in Android integrierte Daten sind Verwenden Sie das ContentProvider-Formular für Entwickler zum Aufrufen (z. B. Video, Audio, Bilder, Adressbücher usw.)
2. Einführung in verwandte Konzepte
1) Einführung in ContentProvider
Wenn eine Anwendung die ContentProvider-Klasse erbt und diese Klasse neu schreibt Methoden zum Bereitstellen von Daten und zum Speichern von Daten, damit diese mit anderen Anwendungen geteilt werden können. Obwohl Daten mit anderen Methoden extern geteilt werden können, unterscheidet sich die Datenzugriffsmethode je nach Art der Datenspeicherung. Wenn Sie beispielsweise den Dateimodus zum externen Teilen von Daten verwenden, müssen Sie Dateivorgänge ausführen, um Daten zu lesen und zu schreiben. Wenn Sie SharedPreferences zum Teilen von Daten verwenden, müssen Sie die SharedPreferences-API zum Lesen und Schreiben von Daten verwenden. Der Vorteil der Verwendung von ContentProvider zum Teilen von Daten besteht in der Vereinheitlichung der Datenzugriffsmethode.
2) Einführung in die Uri-Klasse
Uri uri = Uri.parse("content://com.changcheng.provider.contactprovider/contact")
Die im Content Provider verwendete Abfragezeichenfolge unterscheidet sich vom Standard SQL-Abfrage. Wir verwenden einen speziellen URI, um viele Vorgänge wie Auswählen, Hinzufügen, Löschen, Ändern usw. durchzuführen. Dieser URI besteht aus drei Teilen: „content://“, der den Pfad der Daten darstellt, und einer optionalen Identifikations-ID . Hier sind einige Beispiel-URIs:

content://media/internal/images  这个URI将返回设备上存储的所有图片
content://contacts/people/  这个URI将返回设备上的所有联系人信息
content://contacts/people/45 这个URI返回单个结果(联系人信息中ID为45的联系人记录)

Obwohl dieses Abfragezeichenfolgenformat üblich ist, kann es dennoch etwas verwirrend aussehen. Zu diesem Zweck stellt Android eine Reihe von Hilfeklassen bereit (unter dem Paket android.provider), die viele Abfragezeichenfolgen in Form von Klassenvariablen enthalten. Diese Methode erleichtert uns das Verständnis, wie oben gezeigt: / /contacts/people/45 Dieser URI kann in der folgenden Form geschrieben werden:
Uri person = ContentUris.withAppendedId(People.CONTENT_URI, 45);
Führen Sie dann die Datenabfrage aus:
Cursor cur = ManagedQuery( person, null, null, null);
Diese Abfrage gibt einen Cursor zurück, der alle Datenfelder enthält. Wir können alle Daten erhalten, indem wir diesen Cursor iterieren:

package com.wissen.testApp;
public class ContentProviderDemo extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
displayRecords();
    }
    private void displayRecords() {
 //该数组中包含了所有要返回的字段
     String columns[] = new String[] { People.NAME, People.NUMBER };
Uri mContacts = People.CONTENT_URI;
Cursor cur = managedQuery(
   mContacts,
   columns,  // 要返回的数据字段
  null,   // WHERE子句
  null,  // WHERE 子句的参数
         null  // Order-by子句
     );
if (cur.moveToFirst()) {
    String name = null;
    String phoneNo = null;
    do {
// 获取字段的值
     name = cur.getString(cur.getColumnIndex(People.NAME));
      phoneNo = cur.getString(cur.getColumnIndex(People.NUMBER));
      Toast.makeText(this, name + ” ” + phoneNo, Toast.LENGTH_LONG).show();
   } while (cur.moveToNext());
}
    }
}

Das obige Beispiel zeigt, wie man einliest Sequenz Ruft den angegebenen Datenspaltennamen und die angegebene Nummer in der Kontaktinformationstabelle ab.
Datensätze ändern:
Wir können die Methode ContentResolver.update() verwenden, um Daten zu ändern:

private void updateRecord(int recNo, String name) {
    Uri uri = ContentUris.withAppendedId(People.CONTENT_URI, recNo);
    ContentValues values = new ContentValues();
    values.put(People.NAME, name);
    getContentResolver().update(uri, values, null, null);
}

Jetzt können Sie die obige Methode aufrufen, um die zu aktualisieren angegebener Datensatz:
updateRecord(10, „XYZ“); //Ändern Sie den Namensfeldwert des 10. Datensatzes in „XYZ“
Datensatz hinzufügen:
Um einen Datensatz hinzuzufügen, können wir ContentResolver.insert aufrufen ()-Methode: Diese Methode akzeptiert einen Ziel-URI des hinzuzufügenden Datensatzes und ein Map-Objekt, das den neuen Datensatzwert enthält. Der Rückgabewert nach dem Aufruf ist der URI des neuen Datensatzes, einschließlich der Datensatznummer.
In den obigen Beispielen basieren wir alle auf dem Standard-Content-Provider des Kontaktinformationsbuchs. Jetzt erstellen wir weiterhin eine insertRecord()-Methode, um Daten zum Kontaktinformationsbuch hinzuzufügen:

private void insertRecords(String name, String phoneNo) {
    ContentValues values = new ContentValues();
    values.put(People.NAME, name);
    Uri uri = getContentResolver().insert(People.CONTENT_URI, values);
    Log.d(”ANDROID”, uri.toString());
    Uri numberUri = Uri.withAppendedPath(uri, People.Phones.CONTENT_DIRECTORY);
    values.clear();
    values.put(Contacts.Phones.TYPE, People.Phones.TYPE_MOBILE);
    values.put(People.NUMBER, phoneNo);
    getContentResolver().insert(numberUri, values);
}

Auf diese Weise können wir insertRecords(name, phoneNo) aufrufen, um den Kontaktnamen und die Telefonnummer zum Kontaktinformationsbuch hinzuzufügen.
Datensätze löschen:
Die Methode getContextResolver.delete() im Content Provider kann zum Löschen von Datensätzen verwendet werden. Die folgenden Datensätze werden zum Löschen aller Kontaktinformationen auf dem Gerät verwendet:

private void deleteRecords() {
    Uri uri = People.CONTENT_URI;
    getContentResolver().delete(uri, null, null);
}

你也可以指定WHERE条件语句来删除特定的记录:
getContentResolver().delete(uri, “NAME=” + “‘XYZ XYZ'”, null);
这将会删除name为‘XYZ XYZ'的记录。
3. 创建ContentProvider
要创建我们自己的Content Provider的话,我们需要遵循以下几步:
a. 创建一个继承了ContentProvider父类的类
b. 定义一个名为CONTENT_URI,并且是public static final的Uri类型的类变量,你必须为其指定一个唯一的字符串值,最好的方案是以类的全名称, 如:
public static final Uri CONTENT_URI = Uri.parse( “content://com.google.android.MyContentProvider”);
c. 定义你要返回给客户端的数据列名。如果你正在使用Android数据库,必须为其定义一个叫_id的列,它用来表示每条记录的唯一性。
d. 创建你的数据存储系统。大多数Content Provider使用Android文件系统或SQLite数据库来保持数据,但是你也可以以任何你想要的方式来存储。
e. 如果你要存储字节型数据,比如位图文件等,数据列其实是一个表示实际保存文件的URI字符串,通过它来读取对应的文件数据。处理这种数据类型的Content Provider需要实现一个名为_data的字段,_data字段列出了该文件在Android文件系统上的精确路径。这个字段不仅是供客户端使用,而且也可以供ContentResolver使用。客户端可以调用ContentResolver.openOutputStream()方法来处理该URI指向的文件资源;如果是ContentResolver本身的话,由于其持有的权限比客户端要高,所以它能直接访问该数据文件。
f. 声明public static String型的变量,用于指定要从游标处返回的数据列。
g. 查询返回一个Cursor类型的对象。所有执行写操作的方法如insert(), update() 以及delete()都将被监听。我们可以通过使用ContentResover().notifyChange()方法来通知监听器关于数据更新的信息。
h. 在AndroidMenifest.xml中使用245134590f76a973a830651cacc0946c标签来设置Content Provider。
i. 如果你要处理的数据类型是一种比较新的类型,你就必须先定义一个新的MIME类型,以供ContentProvider.geType(url)来返回。MIME类型有两种形式:一种是为指定的单个记录的,还有一种是为多条记录的。这里给出一种常用的格式:

  vnd.android.cursor.item/vnd.yourcompanyname.contenttype (单个记录的MIME类型)
  比如, 一个请求列车信息的URI如content://com.example.transportationprovider/trains/122 可能就会返回typevnd.android.cursor.item/vnd.example.rail这样一个MIME类型。
  vnd.android.cursor.dir/vnd.yourcompanyname.contenttype (多个记录的MIME类型)
  比如, 一个请求所有列车信息的URI如content://com.example.transportationprovider/trains 可能就会返回vnd.android.cursor.dir/vnd.example.rail这样一个MIME 类型。

下列代码将创建一个Content Provider,它仅仅是存储用户名称并显示所有的用户名称(使用 SQLLite数据库存储这些数据):

public class MyUsers {
    public static final String AUTHORITY  = “com.wissen.MyContentProvider”;
    // BaseColumn类中已经包含了 _id字段
   public static final class User implements BaseColumns {
 public static final Uri CONTENT_URI  = Uri.parse(”content://com.wissen.MyContentProvider”);
 // 表数据列
 public static final String  USER_NAME  = “USER_NAME”;
    }
}

上面的类中定义了Content Provider的CONTENT_URI,以及数据列。下面我们将定义基于上面的类来定义实际的Content Provider类:

public class MyContentProvider extends ContentProvider {
    private SQLiteDatabase     sqlDB;
    private DatabaseHelper    dbHelper;
    private static final String  DATABASE_NAME = “Users.db”;
    private static final int  DATABASE_VERSION= 1;
    private static final String TABLE_NAME= “User”;
    private static final String TAG = “MyContentProvider”;
    private static class DatabaseHelper extends SQLiteOpenHelper {
 DatabaseHelper(Context context) {
     super(context, DATABASE_NAME, null, DATABASE_VERSION);
 }
 @Override
 public void onCreate(SQLiteDatabase db) {
     //创建用于存储数据的表
 db.execSQL(”Create table ” + TABLE_NAME + “( _id INTEGER PRIMARY KEY AUTOINCREMENT, USER_NAME TEXT);”);
 }
 @Override
 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
     db.execSQL(”DROP TABLE IF EXISTS ” + TABLE_NAME);
     onCreate(db);
 }
    }
    @Override
    public int delete(Uri uri, String s, String[] as) {
 return 0;
    }
    @Override
    public String getType(Uri uri) {
 return null;
    }
    @Override
    public Uri insert(Uri uri, ContentValues contentvalues) {
 sqlDB = dbHelper.getWritableDatabase();
 long rowId = sqlDB.insert(TABLE_NAME, “”, contentvalues);
 if (rowId > 0) {
     Uri rowUri = ContentUris.appendId(MyUsers.User.CONTENT_URI.buildUpon(), rowId).build();
     getContext().getContentResolver().notifyChange(rowUri, null);
     return rowUri;
 }
 throw new SQLException(”Failed to insert row into ” + uri);
    }
    @Override
    public boolean onCreate() {
 dbHelper = new DatabaseHelper(getContext());
 return (dbHelper == null) ? false : true;
    }
    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
 SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
 SQLiteDatabase db = dbHelper.getReadableDatabase();
 qb.setTables(TABLE_NAME);
 Cursor c = qb.query(db, projection, selection, null, null, null, sortOrder);
 c.setNotificationUri(getContext().getContentResolver(), uri);
 return c;
    }
    @Override
    public int update(Uri uri, ContentValues contentvalues, String s, String[] as) {
 return 0;
    }
}
一个名为MyContentProvider的Content Provider创建完成了,它用于从Sqlite数据库中添加和读取记录。

Content Provider的入口需要在AndroidManifest.xml中配置:

<provider android:name=”MyContentProvider” android:authorities=”com.wissen.MyContentProvider” />

之后,让我们来使用这个定义好的Content Provider:
1)为应用程序添加ContentProvider的访问权限。
2)通过getContentResolver()方法得到ContentResolver对象。
3)调用ContentResolver类的query()方法查询数据,该方法会返回一个Cursor对象。
4)对得到的Cursor对象进行分析,得到需要的数据。
5)调用Cursor类的close()方法将Cursor对象关闭。

public class MyContentDemo extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 insertRecord(”MyUser”);
 displayRecords();
    }

    private void insertRecord(String userName) {
 ContentValues values = new ContentValues();
 values.put(MyUsers.User.USER_NAME, userName);
 getContentResolver().insert(MyUsers.User.CONTENT_URI, values);
    }
    private void displayRecords() {
 String columns[] = new String[] { MyUsers.User._ID, MyUsers.User.USER_NAME };
 Uri myUri = MyUsers.User.CONTENT_URI;
 Cursor cur = managedQuery(myUri, columns,null, null, null );
 if (cur.moveToFirst()) {
     String id = null;
     String userName = null;
     do {
  id = cur.getString(cur.getColumnIndex(MyUsers.User._ID));
  userName = cur.getString(cur.getColumnIndex(MyUsers.User.USER_NAME));
  Toast.makeText(this, id + ” ” + userName, Toast.LENGTH_LONG).show();
    } while (cur.moveToNext());
}
    }
}

更多基于Android ContentProvider的总结详解相关文章请关注PHP中文网!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn