1. 程式人生 > >Android 自定義ContentProvider和ContentObserver的完整使用

Android 自定義ContentProvider和ContentObserver的完整使用

在自定義ContentProvider結合ContentObserver一起使用時,自己寫的ContentProvider,在執行完insert、delete和update後,要手動地呼叫getContentResolver().notifyChange()這個方法來通知改動的產生。

直接上程式碼:

MainActivity

package com.jackie.contentobserver;


import java.util.ArrayList;

import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;

public class MainActivity extends Activity {

	private ArrayList<Person> mList;
	private ListView mListView;
	private ContentResolver resolver;
	private MyBaseAdapter mBaseAdapter;
	private Handler mHandler;
	
	private AdapterContentObserver mAdapterContentObserver;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		mListView = (ListView) findViewById(R.id.lv_person);
		initData();
		
		mBaseAdapter = new MyBaseAdapter(this, mList);
		mListView.setAdapter(mBaseAdapter);
		
		mHandler = new Handler();
		
		mAdapterContentObserver = new AdapterContentObserver(this, mHandler);
		resolver.registerContentObserver(Uri.parse("content://com.jackie.provider.person/person"), true, mAdapterContentObserver);
		//註冊簡訊變化監聽
		//this.getContentResolver().registerContentObserver(Uri.parse("content://sms/"), true, content)
	}

	@Override
	protected void onDestroy() {
		resolver.unregisterContentObserver(mAdapterContentObserver);
		super.onDestroy();
	}

	private ArrayList<Person> initData() {
		mList = new ArrayList<Person>();
		resolver = getContentResolver();
		Cursor cursor = resolver.query(Uri.parse("content://com.jackie.provider.person/person"), null, null, null, null);
		while (cursor.moveToNext()) {
			Person person = new Person();
			person.set_id(cursor.getInt(cursor.getColumnIndex("_id")));
			person.setName(cursor.getString(cursor.getColumnIndex("name")));
			mList.add(person);
		}
		
		return mList;
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.activity_main, menu);
		return true;
	}

	@Override
	public boolean onMenuItemSelected(int featureId, MenuItem item) {
		switch (item.getItemId()) {
		case R.id.menu_settings:
//			AlertDialog.Builder builder = new AlertDialog.Builder(this);
//			builder.setTitle("提示").setMessage("您確定要退出?");
//			builder.create().show();
			ContentValues values = new ContentValues();
			values.put("name", "Jackie");
			Uri mUri = resolver.insert(Uri.parse("content://com.jackie.provider.person/person"), values);
			
			//方法一: 重新查詢資料庫實時重新整理
//	        mBaseAdapter = new MyBaseAdapter(this, initData());
//	        mListView.setAdapter(mBaseAdapter);
			
			//方法二: 當adapter繫結的list變化時,呼叫adapter的notifyDataSetChanged方法實時重新整理(不用重複查詢資料庫,效率更高)
//			long id = ContentUris.parseId(mUri);
//			mList.add(new Person(id, "chengjie"));
//			mBaseAdapter.notifyDataSetChanged();
			
			//方法三: 內容觀察者ContentObserver
			//自己寫的ContentProvider,在執行完insert、delete和update後,要手動地呼叫getContentResolver().notifyChange()這個方法來通知改動的產生(請參考MyProvider.java的方法)
			
			break;

		default:
			break;
		}
		return super.onMenuItemSelected(featureId, item);
	}

}

AdapterContentObserver.java

package com.jackie.contentobserver;


    import android.content.ContentResolver;
    import android.content.Context;
    import android.database.ContentObserver;
    import android.database.Cursor;
    import android.net.Uri;
    import android.os.Handler;
    import android.util.Log;
    import android.widget.Toast;


    public class AdapterContentObserver extends ContentObserver {
        private Context context;
        private Handler handler;

        private static final int PERSON_UPDATE = 0;


        public AdapterContentObserver(Handler handler) {
            super(handler);
            // TODO Auto-generated constructor stub
        }

        public AdapterContentObserver(Context context, Handler handler) {
            super(handler);
            this.context = context;
            this.handler = handler;
        }


        //當監聽的Uri發生變化,便會執行這個方法
        @Override
        public void onChange(boolean selfChange, Uri uri) {
            super.onChange(selfChange, uri);

            ContentResolver resolver = context.getContentResolver();
            // 獲取最新的一條資料
            Cursor cursor = resolver.query(uri, null, null, null, "_id desc limit 1");
            while (cursor.moveToNext()) {
                int _id = cursor.getInt(cursor.getColumnIndex("_id"));
                Toast.makeText(context, "資料庫更新了, _id 為: " + _id, Toast.LENGTH_SHORT).show();
            }
            cursor.close();
        }
    }

DBHelper.java

package com.jackie.contentobserver;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;

public class DBHelper extends SQLiteOpenHelper {


	public DBHelper(Context context, String name, CursorFactory factory,
			int version) {
		super(context, name, factory, version);
		// TODO Auto-generated constructor stub
	}

	@Override
	public void onCreate(SQLiteDatabase db) {
		db.execSQL("create table if not exists person(_id integer primary key autoincrement, name text)");
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		
	}

}
MyBaseAdapter.java
package com.jackie.contentobserver;

import java.util.ArrayList;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

public class MyBaseAdapter extends BaseAdapter {

	private ViewHolder holder;
	private Context context;
	private ArrayList<Person> mList;
	
	public MyBaseAdapter(Context context, ArrayList<Person> mList) {
		this.context = context;
		this.mList = mList;
	}

	@Override
	public int getCount() {
		return mList.size();
	}

	@Override
	public Object getItem(int position) {
		return mList.get(position);
	}

	@Override
	public long getItemId(int position) {
		return position;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		LayoutInflater mInflater = LayoutInflater.from(context);
		if (convertView == null) {
			holder = new ViewHolder();
			convertView = mInflater.inflate(R.layout.listview_item, null);
			holder.idTexitView = (TextView) convertView.findViewById(R.id.tv_id);
			holder.nameTextView = (TextView) convertView.findViewById(R.id.tv_name);
			convertView.setTag(holder);
		} else {
			holder = (ViewHolder) convertView.getTag();
		}
		holder.idTexitView.setText(mList.get(position).get_id() + "");
		holder.nameTextView.setText(mList.get(position).getName());
		return convertView;
	}
	
	class ViewHolder {
		TextView idTexitView;
		TextView nameTextView;
	}
}

MyProvider.java

package com.jackie.contentobserver;

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;

public class MyProvider extends ContentProvider {
	private final static String AUTHORITH = "com.jackie.provider.person";
	
	private final static String PERSONS_PATH = "person";
	
	private final static String PERSON_PATH = "person/#";
	
	private final static int PERSON = 1;
	
	private final static int PERSONS = 2;
	
	private final static String DATABASE_NAME = "person_db";
	
	private final static String TABLE_NAME = "person";
	
	private final static String TABLE_COLUMN_ID = "_id";
	
	private final static String TABLE_COLUMN_NAME = "name";
	
	private final static UriMatcher mUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
	
	static {
		mUriMatcher.addURI(AUTHORITH, PERSONS_PATH, PERSONS);
		mUriMatcher.addURI(AUTHORITH, PERSON_PATH, PERSON);
	}
	
	private DBHelper helper = null;

	@Override
	public boolean onCreate() {
		helper  = new DBHelper(getContext(), DATABASE_NAME, null, 1);
		return true;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		SQLiteDatabase database = helper.getWritableDatabase();
		switch (mUriMatcher.match(uri)) {
		case PERSON:
			long id = ContentUris.parseId(uri);
			String where = TABLE_COLUMN_ID + "=" + id;
			if (selection != null && !"".equals(selection)) {
				selection = where + "and" + selection;
			}
			return database.query(TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder);
			
		case PERSONS:
			return database.query(TABLE_NAME, projection, selection, selectionArgs, null, null, sortOrder);
			
		default:
			throw new IllegalArgumentException("UnKnown uri: " + uri);
		}
	}

	@Override
	public String getType(Uri uri) {
		switch (mUriMatcher.match(uri)) {
		case PERSON:
			return "vnd.android.cursor.item";
			
		case PERSONS:
			return "vnd.android.cursor.dir";
			
		default:
			throw new IllegalArgumentException("UnKnown uri: " + uri);
		}
	}

	@Override
	public Uri insert(Uri uri, ContentValues values) {
		SQLiteDatabase database = helper.getWritableDatabase();
		long id = database.insert(TABLE_NAME, TABLE_COLUMN_NAME, values);
		//向外界通知該ContentProvider裡的資料發生了變化 ,以便ContentObserver作出相應
                getContext().getContentResolver().notifyChange(uri, null);
		return ContentUris.withAppendedId(uri, id);
	}

	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		SQLiteDatabase database = helper.getWritableDatabase();
		switch (mUriMatcher.match(uri)) {
		case PERSON:
			long id = ContentUris.parseId(uri);
			String where = TABLE_COLUMN_ID + "=" + id;
			if (selection != null && !"".equals(selection)) {
				selection = where + "and" + selection;
			}
			return database.delete(TABLE_NAME, selection, selectionArgs);
			
		case PERSONS:
			return database.delete(TABLE_NAME, selection, selectionArgs);
			
		default:
			throw new IllegalArgumentException("UnKnown uri: " + uri);
		}
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		// TODO Auto-generated method stub
		return 0;
	}

}

Person.java

package com.jackie.contentobserver;

public class Person {
	
	private long _id;
	private String name;
	public Person(long _id, String name) {
		super();
		this._id = _id;
		this.name = name;
	}
	
	public Person() {
		super();
		// TODO Auto-generated constructor stub
	}
	
	public long get_id() {
		return _id;
	}
	
	public void set_id(long _id) {
		this._id = _id;
	}
	
	public String getName() {
		return name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	

}