I’m going to make a ContentProvider for Android

I believe you are familiar with the top four components of Android. Today we are going to talk about the use of ContentProvider. Everything is basic and most important, but people are forgetful animals, so they need to write down notes and review them often. May we be who we really are.

ContentProvider profile

Access data from the Provider provided by the system

  • Composition of the content URI
  • ContentResolve class

Create your own Provider

  • UriMater class
  • Customize the steps of a Provider

A ContentProvider also stores data, but unlike Android’s built-in database, SharedPreferences, and file storage methods, which allow different applications to share data, It can also choose which parts of the data to share, thus ensuring that the private data in the program is not at risk of leakage. So the component ContentProvider is responsible for storing and sharing data.

Contentproviders come in two forms: you can use existing content providers to read and manipulate data in a program, or you can create your own content providers to provide external access to the program’s data.

2. Access data from the Provider provided by the system

In other words, other applications can use the ContentProvider to add, delete, alter, and query data in an application. In SQLite data storage, we mentioned that you can add, delete, alter, and query data in an application. In fact, the ContentProvider is a further encapsulation of SQLiteOpenHelper, but instead of using a table name to indicate which table is being operated on, since it is now accessed by other programs, it uses a well-formatted content URI instead. Let’s learn the composition of a URI.

(1) URI composition

Before learning the demo database, for example, its package name is com. Example. Myapplication, if other applications to access the program student. The student table in the db, so need content URI as shown:

As you can see, the content URI is a very clear representation of which table in which program we want to access, but that’s not all. It needs to be parsed into a URI object before it can be passed in as a parameter. The content Uri string can be parsed into a Uri object by calling the uri.parse () method:

The Uri class is specifically designed to do this link transformation. In fact, this link method is very similar to HTTP. Content: the package name cannot be changed. Provider: the table name.

(2) ContentResolve class

We now have urIs that look like “table names,” and similarly, the set of methods provided in the ContentResolver class for adding, deleting, changing, and querying data look like the auxiliary methods of SQLiteDatabase: The insert() method is used to add data, the update() method is used to update data, the delete() method is used to delete data, and the query() method is used to query data. Not only do they have the same method name, but they also provide very similar parameters, as shown below, with the differences in red:

So if other programs want to access the shared data in the ContentProvider, they can do this:

First: instantiate a ContentResolver object using the getContentResolver() method in Context.

Second: invoke the object’s add, delete, change, and query methods to manipulate the data in the ContentProvider.

Let’s look at the basic code for querying contact data:

Don’t forget to declare permissions in your registration file

Not only that, but Android 6.0 has runtime permissions, so we need to add judgment.

This section is generic code that you can wrap in BaseActivity as you go along. This can increase code reuse.

This is the icon that needs to apply permissions dynamically, but it doesn’t matter, you can look it up if you don’t remember.

3. Create your own Provider

(1) UriMater class

The UriMater class has the ability to match content URIs. It uses two methods: the addURI() method to pass in the URI, which takes three arguments (permission, path, and a custom code); The other is the match() method, which matches urIs. It receives a URI object and returns some custom code that matches the URI object. Using this custom code, you can determine which table the caller expects to access.

(2) Customize the steps of a Provider

Step 1: Create a new class to inherit the ContentProvider. Step 2: Rewrite the six abstract methods of ContentProvider, as shown in the figure below:

Public class MyProvider extends ContentProvider {@override public Boolean onCreate() {return  false; } @override public Cursor query(@nonnull Uri Uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) { return null; } @nullable @override // Used to return the MIME type represented by the current Uri public String getType(@nonnull Uri Uri) {return null; } @nullable @override public Uri insert(@nonnull Uri Uri) @Nullable ContentValues values) { return null; @override public int delete(@nonnull Uri Uri, @nullable String Selection, @Nullable String[] selectionArgs) { return 0; @override public int update(@nonnull Uri Uri, @nullable ContentValues values, @override public int update(@nonnull Uri Uri, @nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) { return 0; }}Copy the code

Step 3: Register in the configuration file and specify the following attributes:

Provider Android: Name Is the full name of the Provider, in the form of the package name. The class name Android: Exported =”true” specifies that the Provider is accessible by other applications.

(3) Example: Create MyProvider for student.db

Create a custom provider MyProvider for our database demo and use it to manipulate the student.db data in other applications.

Start customizing providers! We started by defining four constants representing access to all data in the Student table, access to a single data in the Student table (student/# is used to represent any row in the Student table), access to all data in the course table, and access to a single data in the course table. The UriMatcher is then initialized in a static code block, adding the URI formats expected to match.

The onCreate() method creates an instance of MyHelper and returns true to indicate that the content provider initialized successfully. The database has now been created or upgraded.

Next comes the getType() method, which returns a MIME string. The MIME string corresponding to a content URI consists of three parts, which are formatted as follows: it must start with VND; If the content URI ends in a path, it is followed by Android.cursor. dir/; if the content URI ends in id, it is followed by Android.cursor.item /; VND.< authority>.< path>. So the MIME strings corresponding to the four content URIs are:

The query() method obtains an instance of SQLiteDatabase, determines which table the user wants to access based on the Uri parameter passed in, and then calls SQLiteDatabase’s Query () and returns the Cursor object. Note that the getPathSegments() method of the Uri object is called when accessing a single piece of data. This splits the portion of the content Uri after the permission with a “/” and places the split result in a list of strings in which the 0th position is the path and the first position is the ID. After obtaining the ID, the selection and selectionArgs parameters are used to constrain the query of a single piece of data.

Other methods are not said, you can try, don’t forget to register OK.

A transaction is the basic unit of recovery and concurrency control.

Transactions should have four attributes: atomicity, consistency, isolation, and persistence. These four properties are commonly referred to as ACID properties.

Atomicity. A transaction is an indivisible unit of work in which all or none of the operations involved are performed.

Consistency. Transactions must change the database from one consistent state to another. Consistency is closely related to atomicity.

Isolation. The execution of a transaction cannot be interfered with by other transactions. That is, the operations and data used within a transaction are isolated from other concurrent transactions, and the concurrent transactions cannot interfere with each other.

They are persistent. Permanence, also known as permanence, means that once a transaction is committed, its changes to data in the database should be permanent. Subsequent operations or failures should not affect it in any way.

/** * SQLite transaction management */ public voidtransation() { SQLiteDatabase db = helper.getWritableDatabase(); Db.begintransaction (); ExecSQL (execexecsql (execexecsql (execexecsql (execexecsql))"update person set age = age-1 where name = 'xiaohong'");
			db.execSQL("update person set age = age+1 where name = 'xiaolan'"); / / db transaction success. SetTransactionSuccessful (); } finally {// endTransaction db.endtransaction (); }}Copy the code

Using transactions can improve efficiency when using sqLite databases to bulk insert data.

There are areas where you can optimize when using sqLite databases.

In Android, both the insert,delete and execSQL methods of SQLiteDatabase and execSQL are enabled to enable transactions to ensure that each operation is atomic, so that the result is either the correct result after the operation or before the operation. So we can show support for transactions, so that the transaction operation opens significantly less.

Create index create index

CREATE INDEX index_name ON table_name;

Three: Close Cursor in time

4: Time consuming Asynchronous database operations are local I/OS and usually time-consuming. If they are not handled properly, ANR may occur. Therefore, it is recommended that these time-consuming operations be processed in asynchronous threads.

Today’s state is not good enough, the writing is not very complete, I hope you can forgive me. May we be who we really are.