day3-day4 android 内容提供者-观察者-listview -demo

1,布局文件

<?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="wrap_content"
    android:orientation="horizontal"
    android:padding="10dp" >

    <TextView
        android:id="@+id/idTV"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="13"
        android:textColor="#000000"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/nameTV"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="2"
        android:singleLine="true"
        android:text="PQ"
        android:textColor="#000000"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/balanceTV"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="2"
        android:singleLine="true"
        android:text="12345"
        android:textColor="#000000"
        android:textSize="20sp" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

        <ImageView
            android:id="@+id/upIV"
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.itheima.sqlite"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="10"
        android:targetSdkVersion="17" />
    
    <instrumentation
        android:name="android.test.InstrumentationTestRunner"
        android:targetPackage="com.itheima.sqlite" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        
	   	<uses-library android:name="android.test.runner" />
        
        <activity
            android:name="com.itheima.sqlite.ui.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        
        <provider
            android:name="com.itheima.sqlite.provider.ItheimaProvider"
            android:authorities="com.itheima.ItheimaProvider" />

    </application>

</manifest>

android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="2dp" android:src="@android:drawable/arrow_up_float" /> <ImageView android:id="@+id/downIV" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@android:drawable/arrow_down_float" /> </LinearLayout> <ImageView android:id="@+id/deleteIV" android:layout_width="25dp" android:layout_height="25dp" android:src="@android:drawable/ic_menu_delete" /></LinearLayout>


2,清单文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.itheima.sqlite"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="10"
        android:targetSdkVersion="17" />
    
    <instrumentation
        android:name="android.test.InstrumentationTestRunner"
        android:targetPackage="com.itheima.sqlite" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        
	   	<uses-library android:name="android.test.runner" />
        
        <activity
            android:name="com.itheima.sqlite.ui.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        
        <provider
            android:name="com.itheima.sqlite.provider.ItheimaProvider"
            android:authorities="com.itheima.ItheimaProvider" />

    </application>

</manifest>
3,item 布局文件

<?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="wrap_content"
    android:orientation="horizontal"
    android:padding="10dp" >

    <TextView
        android:id="@+id/idTV"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="13"
        android:textColor="#000000"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/nameTV"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="2"
        android:singleLine="true"
        android:text="PQ"
        android:textColor="#000000"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/balanceTV"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="2"
        android:singleLine="true"
        android:text="12345"
        android:textColor="#000000"
        android:textSize="20sp" />

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical" >

        <ImageView
            android:id="@+id/upIV"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="2dp"
            android:src="@android:drawable/arrow_up_float" />

        <ImageView
            android:id="@+id/downIV"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@android:drawable/arrow_down_float" />
    </LinearLayout>

    <ImageView
        android:id="@+id/deleteIV"
        android:layout_width="25dp"
        android:layout_height="25dp"
        android:src="@android:drawable/ic_menu_delete" />

</LinearLayout>

4,domain 类

package com.itheima.sqlite.bean;

public class Account {
	private Long id;			
	private String name;
	private Integer balance;
	
	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getBalance() {
		return balance;
	}

	public void setBalance(Integer balance) {
		this.balance = balance;
	}

	public Account(Long id, String name, Integer balance) {
		super();
		this.id = id;
		this.name = name;
		this.balance = balance;
	}

	public Account(String name, Integer balance) {
		super();
		this.name = name;
		this.balance = balance;
	}

	public Account() {
		super();
	}

	@Override
	public String toString() {
		return "[序号: " + id + ", 姓名: " + name + ", 余额: " + balance + "]";
	}

}

5,Myhelper 类

package com.itheima.sqlite.dao;

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

public class MyHelper extends SQLiteOpenHelper {
	
	// 由于父类没有无参构造函数, 所以子类必须指定调用父类哪个有参的构造函数
	public MyHelper(Context context) {
		super(context, "itheima.db", null, 2);
	}

	@Override
	public void onCreate(SQLiteDatabase db) {
		System.out.println("onCreate");
		db.execSQL("CREATE TABLE account(_id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(20), balance INTEGER)");
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		System.out.println("onUpgrade");
		db.execSQL("ALTER TABLE account ADD balance INTEGER");
	}
	
}

6,accountDao类

package com.itheima.sqlite.dao;

import java.util.ArrayList;
import java.util.List;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import com.itheima.sqlite.bean.Account;

public class AccountDao {
	private MyHelper helper;
	
	public AccountDao(Context context) {
		helper = new MyHelper(context);		// 创建Dao时, 创建Helper
	}

	public void insert(Account account) {
		SQLiteDatabase db = helper.getWritableDatabase();	// 获取数据库对象
		ContentValues values = new ContentValues();			// 用来装载要插入的数据的 Map<列名, 列的值>
		values.put("name", account.getName());
		values.put("balance", account.getBalance());
		long id = db.insert("account", null, values);		// 向account表插入数据values, 得到id
		account.setId(id);		
		db.close();				// 关闭数据库
		
		// db.insert() 方法的第二个参数, 如果写null, 是无法插入一条空数据的
		// 如果想插入一条空数据, 第二个参数必须写一个列名(任意列)
		// 这个列名是用来拼接SQL语句用的.
		// INSERT INTO account(null) VALUES(NULL)
	}

	public int delete(long id) {
		SQLiteDatabase db = helper.getWritableDatabase();	
		int count = db.delete("account", "_id=?", new String[] { id + "" });	// 按条件删除指定表中的数据, 返回受影响的行数
		db.close();	
		return count;
	}

	public int update(Account account) {
		SQLiteDatabase db = helper.getWritableDatabase();	
		ContentValues values = new ContentValues();			// 要修改的数据
		values.put("name", account.getName());
		values.put("balance", account.getBalance());
		int count = db.update("account", values, "_id=?", new String[] { account.getId() + "" });	// 更新并得到行数
		db.close();		
		return count;
	}

	public Account query(long id) {
		SQLiteDatabase db = helper.getReadableDatabase();	// 获取数据库对象
		Cursor c = db.query("account", new String[]{"name", "balance"}, "_id=?", new String[]{ id + "" }, null, null, null);
		Account a = null;
		if (c.moveToNext()) {	// 从Cursor中获取数据, 封装成Account对象
			String name = c.getString(0);
			int balance = c.getInt(1);
			a = new Account(id, name, balance);
		}
		c.close();	// 关闭结果集
		db.close();	// 关闭数据库
		return a;	// 返回对象
	}
	
	public List<Account> queryAll() {
		SQLiteDatabase db = helper.getReadableDatabase();	
		Cursor c = db.query("account", null, null, null, null, null, "balance DESC");
		List<Account> list = new ArrayList<Account>();
		while (c.moveToNext()) {	
			long id = c.getLong(c.getColumnIndex("_id"));	// 可以根据列名获取索引
			String name = c.getString(1);
			int balance = c.getInt(2);
			list.add(new Account(id, name, balance));
		}
		c.close();	
		db.close();	
		return list;	
	}
	
	public List<Account> queryPage(int pageNum, int pageSize) {
		String index = (pageNum - 1) * pageSize + "";	// 用来分页的索引
		String count = pageSize + "" ;					// 每页取多少条数据
		
		SQLiteDatabase db = helper.getReadableDatabase();	
		Cursor c = db.query("account", null, null, null, null, null, null, index + "," + count);
		List<Account> list = new ArrayList<Account>();
		while (c.moveToNext()) {	
			long id = c.getLong(c.getColumnIndex("_id"));	
			String name = c.getString(1);
			int balance = c.getInt(2);
			list.add(new Account(id, name, balance));
		}
		c.close();	
		db.close();	
		return list;	
	}
	
	public int queryCount() {
		SQLiteDatabase db = helper.getReadableDatabase();	
		Cursor c = db.query("account", new String[] { " COUNT(*)" }, null, null, null, null, null);
		c.moveToNext();
		int count = c.getInt(0);
		c.close();	
		db.close();	
		return count;
	}
	
	public void remit(int fromId, int toId, int amount) {
		SQLiteDatabase db = helper.getWritableDatabase();	
		try {
			db.beginTransaction();			// 开启事务
			db.execSQL("UPDATE account SET balance=balance-? WHERE _id=?", new Object[] { amount, fromId });	
			db.execSQL("UPDATE account SET balance=balance+? WHERE _id=?", new Object[] { amount, toId });	
			db.setTransactionSuccessful();	// 设置事务成功
		} finally {
			db.endTransaction();			// 结束事务, 会提交最后一个成功标记之前的代码
			db.close();		
		}
	}

}

7,classisAccountDao类

package com.itheima.sqlite.dao;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

import com.itheima.sqlite.bean.Account;

public class ClassicAccountDao {
	private MyHelper helper;
	
	public ClassicAccountDao(Context context) {
		helper = new MyHelper(context);		// 创建Dao时, 创建Helper
	}

	public void insert(Account account) {
		SQLiteDatabase db = helper.getWritableDatabase();	// 获取数据库对象
		db.execSQL("INSERT INTO account(name, balance) VALUES(?, ?)", new Object[]{ account.getName(), account.getBalance() });	// 执行插入操作
		Cursor c = db.rawQuery("SELECT _id FROM account ORDER BY _id DESC LIMIT 1", null);	// 获取最后1个id
		c.moveToNext();			// 移动游标
		long id = c.getLong(0);	// 获取id的值
		account.setId(id);		// 给Account对象设置id
		c.close();
		db.close();				// 关闭数据库
	}

	public void delete(long id) {
		SQLiteDatabase db = helper.getWritableDatabase();	
		db.execSQL("DELETE FROM account WHERE _id=?", new Object[]{ id });	
		db.close();	
	}

	public void update(Account account) {
		SQLiteDatabase db = helper.getWritableDatabase();	
		db.execSQL("UPDATE account SET name=?, balance=? WHERE _id=?", new Object[]{ account.getName(), account.getBalance(), account.getId() });	
		db.close();		
	}

	public Account query(long id) {
		SQLiteDatabase db = helper.getReadableDatabase();	// 获取数据库对象
		Cursor c = db.rawQuery("SELECT name, balance FROM account WHERE _id=?", new String[]{ id + "" });	// 执行查询操作, 得到Cursor对象
		Account a = null;
		if (c.moveToNext()) {	// 从Cursor中获取数据, 封装成Account对象
			String name = c.getString(0);
			int balance = c.getInt(1);
			a = new Account(id, name, balance);
		}
		c.close();	// 关闭结果集
		db.close();	// 关闭数据库
		return a;	// 返回对象
	}
	
	public List<Account> queryAll() {
		SQLiteDatabase db = helper.getReadableDatabase();	
		Cursor c = db.rawQuery("SELECT _id, name, balance FROM account", null);
		List<Account> list = new ArrayList<Account>();
		while (c.moveToNext()) {	
			long id = c.getInt(c.getColumnIndex("_id"));	// 可以根据列名获取索引
			String name = c.getString(1);
			int balance = c.getInt(2);
			list.add(new Account(id, name, balance));
		}
		c.close();	
		db.close();	
		return list;	
	}
	
	public List<Account> queryPage(int pageNum, int pageSize) {
		String index = (pageNum - 1) * pageSize + "";	// 用来分页的索引
		String count = pageSize + "" ;					// 每页取多少条数据
		
		SQLiteDatabase db = helper.getReadableDatabase();	
		Cursor c = db.rawQuery("SELECT _id, name, balance FROM account LIMIT ?,?", new String[]{ index , count});
		List<Account> list = new ArrayList<Account>();
		while (c.moveToNext()) {	
			long id = c.getInt(c.getColumnIndex("_id"));	
			String name = c.getString(1);
			int balance = c.getInt(2);
			list.add(new Account(id, name, balance));
		}
		c.close();	
		db.close();	
		return list;	
	}
	
	public int queryCount() {
		SQLiteDatabase db = helper.getReadableDatabase();	
		Cursor c = db.rawQuery("SELECT COUNT(*) FROM account", null);
		c.moveToNext();
		int count = c.getInt(0);
		c.close();	
		db.close();	
		return count;	
	}
	
	public void remit(int fromId, int toId, int amount) {
		SQLiteDatabase db = helper.getWritableDatabase();	
		try {
			db.beginTransaction();			// 开启事务
			db.execSQL("UPDATE account SET balance=balance-? WHERE _id=?", new Object[] { amount, fromId });	
			db.execSQL("UPDATE account SET balance=balance+? WHERE _id=?", new Object[] { amount, toId });	
			db.setTransactionSuccessful();	// 设置事务成功
		} finally {
			db.endTransaction();			// 结束事务, 会提交最后一个成功标记之前的代码
			db.close();		
		}
	}

}

8,provider类

package com.itheima.sqlite.provider;

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 com.itheima.sqlite.dao.MyHelper;

public class ItheimaProvider extends ContentProvider {
	private MyHelper helper;
	private UriMatcher matcher;
	
	private static final int ACCOUNT_ID = 0;
	private static final int ACCOUNT = 1;
	private static final int PERSON = 2;

	public boolean onCreate() { 	// 创建的时候自动执行
		System.out.println("onCreate");
		helper = new MyHelper(getContext());
		matcher = new UriMatcher(UriMatcher.NO_MATCH);							// 用来匹配Uri的工具
		matcher.addURI("com.itheima.ItheimaProvider", "account/#", ACCOUNT_ID);	// 带id的Uri
		matcher.addURI("com.itheima.ItheimaProvider", "account", ACCOUNT);		// 添加可以识别的Uri
		matcher.addURI("com.itheima.ItheimaProvider", "person", PERSON);
		return false;
	}

	public Uri insert(Uri uri, ContentValues values) {
		switch (matcher.match(uri)) {							// 判断参数uri是否是我们可以识别的Uri
			case ACCOUNT:
				SQLiteDatabase db = helper.getWritableDatabase();
				long id = db.insert("account", "_id", values);
				getContext().getContentResolver().notifyChange(uri, null);	// 通知数据修改
				db.close();
				return ContentUris.withAppendedId(uri, id);		// 在原始Uri中追加上id, 返回
			case PERSON:
				System.out.println("目前还没有person表");
				return null;
			default:
				throw new IllegalArgumentException("Uri无法识别: " + uri);
		}
	}

	public int delete(Uri uri, String selection, String[] selectionArgs) {
		switch (matcher.match(uri)) {							
			case ACCOUNT_ID:
				long id = ContentUris.parseId(uri);		// 获取id
				selection = "_id=?";
				selectionArgs = new String[] { id + "" };
			case ACCOUNT:
				SQLiteDatabase db = helper.getWritableDatabase();
				int count = db.delete("account", selection, selectionArgs);
				getContext().getContentResolver().notifyChange(uri, null);
				db.close();
				return count;
			case PERSON:
				System.out.println("目前还没有person表");
				return 0;
			default:
				throw new IllegalArgumentException("Uri无法识别: " + uri);
		}
	}

	public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
		switch (matcher.match(uri)) {							
			case ACCOUNT_ID:
				long id = ContentUris.parseId(uri);		// 获取id
				selection = "_id=?";
				selectionArgs = new String[] { id + "" };
			case ACCOUNT:
				SQLiteDatabase db = helper.getWritableDatabase();
				int count = db.update("account", values, selection, selectionArgs);
				getContext().getContentResolver().notifyChange(uri, null);
				db.close();
				return count;
			case PERSON:
				System.out.println("目前还没有person表");
				return 0;
			default:
				throw new IllegalArgumentException("Uri无法识别: " + uri);
		}
	}

	public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
		switch (matcher.match(uri)) {							
			case ACCOUNT_ID:
				long id = ContentUris.parseId(uri);		// 获取id
				selection = "_id=?";
				selectionArgs = new String[] { id + "" };
			case ACCOUNT:
				SQLiteDatabase db = helper.getReadableDatabase();
				Cursor c = db.query("account", projection, selection, selectionArgs, null, null, sortOrder);
				return c;
			case PERSON:
				System.out.println("目前还没有person表");
				return null;
			default:
				throw new IllegalArgumentException("Uri无法识别: " + uri);
		}
	}

	public String getType(Uri uri) {	// 获取指定Uri的类型
		switch (matcher.match(uri)) {							
			case ACCOUNT_ID:
				return "vnd.android.cursor.item/account";
			case ACCOUNT:
				return "vnd.android.cursor.dir/account";
			default:
				throw new IllegalArgumentException("Uri无法识别: " + uri);
		}
	}
}


9,DBTest类

package com.itheima.sqlite.test;

import java.util.List;

import android.test.AndroidTestCase;

import com.itheima.sqlite.bean.Account;
import com.itheima.sqlite.dao.AccountDao;
import com.itheima.sqlite.dao.MyHelper;

public class DBTest extends AndroidTestCase {
	/*
	 * 打包.apk, 安装到手机
	 * 运行测试机
	 * 创建AndroidTestCase对象 - 初始化成员变量 - 构造函数
	 * 对象创建完成之后, 测试机会把当前应用的Context对象通过setContext()方法设置进来
	 * 执行测试方法
	 * 
	 * 在测试类的成员变量, 或者构造函数中, 不能调用getContext(), 因为还没设置进来, 会得到null
	 */
	
	public void testCreate() {
		MyHelper helper = new MyHelper(getContext());	// 测试类中使用getContext()方法获取Context对象, Activity: this, getApplicationContext()
		helper.getWritableDatabase();
		/*
		 * 获取数据库对象
		 * 		1.数据库不存在: 创建数据库, 执行onCreate()
		 * 		2.数据库存在:   
		 * 			a.版本号没变: 什么都不做
		 * 			b.版本号提升: onUpgrade()
		 * 			c.版本号降低: onDowngrade() 
		 */
	}
	
	public void testInsert() {
		AccountDao dao = new AccountDao(getContext());
		dao.insert(new Account("insert", 9999));
		
		/*for (int i = 1; i <= 100; i++) {
			Account account = new Account("Test" + i, new Random().nextInt(10000)); 
			dao.insert(account);							// 执行插入操作
		}*/
	}
	
	public void testUpdate() {
		Account a1 = new Account(1L, "朴乾", 10000); 
		Account a2 = new Account(3L, "付东", 10000); 
		AccountDao dao = new AccountDao(getContext());	// 创建Dao
		System.out.println(dao.update(a1));
		System.out.println(dao.update(a2));
	}
	
	public void testDelete() {
		AccountDao dao = new AccountDao(getContext());	// 创建Dao
		System.out.println(dao.delete(215));
		System.out.println(dao.delete(216));
		System.out.println(dao.delete(217));
	}
	
	public void testQuery() {
		AccountDao dao = new AccountDao(getContext());
		System.out.println(dao.query(1));
		System.out.println(dao.query(2));
		System.out.println(dao.query(3));
	}
	
	public void testQueryAll() {
		AccountDao dao = new AccountDao(getContext());
		List<Account> list = dao.queryAll();
		for (Account account : list) {
			System.out.println(account);
		}
	}
	
	public void testQueryPage() {
		AccountDao dao = new AccountDao(getContext());
		List<Account> list = dao.queryPage(2, 20);
		for (Account account : list) {
			System.out.println(account);
		}
	}
	
	public void testQueryCount() {
		AccountDao dao = new AccountDao(getContext());
		System.out.println(dao.queryCount());
	}
	
	public void testRemit() {
		AccountDao dao = new AccountDao(getContext());
		dao.remit(1, 3, 100);
	}
	
}

11,MainActivity类

package com.itheima.sqlite.ui;

import java.util.List;

import android.app.Activity;
import android.app.AlertDialog.Builder;
import android.content.DialogInterface;
import android.database.ContentObserver;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.itheima.sqlite.R;
import com.itheima.sqlite.bean.Account;
import com.itheima.sqlite.dao.AccountDao;

public class MainActivity extends Activity {

	private List<Account> list;
	private AccountDao dao;
	private EditText nameET;
	private EditText balanceET;
	private MyAdapter adapter;
	private ListView accountLV;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		dao = new AccountDao(this);
		list = dao.queryAll();											// 从数据库查询出所有数据		
		accountLV = (ListView) findViewById(R.id.accountLV);
		adapter = new MyAdapter();
		accountLV.setAdapter(adapter);									// 给ListView添加适配器(自动把数据生成条目)
		accountLV.setOnItemClickListener(new MyOnItemClickListener());	// 添加监听器, 监听条目点击事件
		
		nameET = (EditText) findViewById(R.id.nameET);
		balanceET = (EditText) findViewById(R.id.balanceET);
		
		// 注册内容观察者(ContentObserver), 监听内容提供者(ContentProvider)的数据变化
		Uri uri = Uri.parse("content://com.itheima.ItheimaProvider");
		getContentResolver().registerContentObserver(uri, true, new MyObserver());
	}
	
	private class MyObserver extends ContentObserver {
		public MyObserver() {
			super(new Handler());					// 处理器, 后面会学, 这里没用
		}
		public void onChange(boolean selfChange) {	// 如果收到数据修改通知, 就执行
			list = dao.queryAll();					// 查询出新的数据
			adapter.notifyDataSetChanged();			// 刷新ListView数据
		}
	}
	
	public void add(View v) {
		String name = nameET.getText().toString().trim();
		String balance = balanceET.getText().toString().trim();
		Account a = new Account(name, balance.equals("") ? 0 : Integer.parseInt(balance));
		dao.insert(a);						// 插入数据库
		list.add(a);						// 插入集合
		adapter.notifyDataSetChanged();		// 刷新界面
		accountLV.setSelection(accountLV.getCount() - 1);	// 移动到最后一个
		nameET.setText("");
		balanceET.setText("");
	}

	// 自定义一个适配器(把数据装到ListView的工具)
	private class MyAdapter extends BaseAdapter {
		public int getCount() {						// 获取条目总数
			return list.size();
		}
		public Object getItem(int position) {		// 根据位置获取对象
			return list.get(position);
		}
		public long getItemId(int position) {		// 根据位置获取id
			return position;
		}
		public View getView(int position, View convertView, ViewGroup parent) {			// 获取一个条目视图
			View item = convertView != null ? convertView : View.inflate(getApplicationContext(), R.layout.item, null);		// 重用convertView
			TextView idTV = (TextView) item.findViewById(R.id.idTV);					// 获取该视图中的TextView
			TextView nameTV = (TextView) item.findViewById(R.id.nameTV);
			TextView balanceTV = (TextView) item.findViewById(R.id.balanceTV);
			
			final Account a = list.get(position);	// 根据当前位置获取Account对象
			idTV.setText(a.getId() + "");			// 把Account对象中的数据放到TextView中
			nameTV.setText(a.getName());
			balanceTV.setText(a.getBalance() + "");
			
			ImageView upIV = (ImageView) item.findViewById(R.id.upIV);
			ImageView downIV = (ImageView) item.findViewById(R.id.downIV);
			ImageView deleteIV = (ImageView) item.findViewById(R.id.deleteIV);
			
			upIV.setOnClickListener(new OnClickListener() {
				public void onClick(View v) {
					a.setBalance(a.getBalance() + 1);	// 修改值
					notifyDataSetChanged();				// 刷新界面
					dao.update(a);						// 更新数据库
				}
			});
			
			downIV.setOnClickListener(new OnClickListener() {
				public void onClick(View v) {
					a.setBalance(a.getBalance() - 1);	
					notifyDataSetChanged();				
					dao.update(a);						
				}
			});
			
			deleteIV.setOnClickListener(new OnClickListener() {
				public void onClick(View v) {
					android.content.DialogInterface.OnClickListener listener = new android.content.DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog, int which) {
							list.remove(a);				// 从集合中删除
							dao.delete(a.getId());		// 从数据库中删除
							notifyDataSetChanged();		// 刷新界面
						}
					};
					
					Builder builder = new Builder(MainActivity.this);	// 创建对话框
					builder.setTitle("确定要删除吗?");					// 设置标题
					builder.setPositiveButton("确定", listener);			// 设置确定按钮的文本以及监听器
					builder.setNegativeButton("取消", null);				// 设置取消按钮
					builder.show();										// 显示对话框
				}
			});
			
			return item;
		}
	}
	
	private class MyOnItemClickListener implements OnItemClickListener {
		public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
			Account a = (Account) parent.getItemAtPosition(position);		// 获取点击位置上的数据
			Toast.makeText(getApplicationContext(), a.toString(), Toast.LENGTH_SHORT).show();
		}
	}
	
}

12,string.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">01.SQLite</string>
    <string name="action_settings">Settings</string>
    <string name="hello_world">Hello world!</string>

</resources>

13,style.xml

<resources>

    <!--
        Base application theme, dependent on API level. This theme is replaced
        by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
    -->
    <style name="AppBaseTheme" parent="android:Theme.Light">
        <!--
            Theme customizations available in newer API levels can go in
            res/values-vXX/styles.xml, while customizations related to
            backward-compatibility can go here.
        -->
    </style>

    <!-- Application theme. -->
    <style name="AppTheme" parent="AppBaseTheme">
        <item name="android:windowNoTitle">true</item>			<!-- 没有标题栏 -->
        <item name="android:windowFullscreen">true</item>		<!-- 全屏 -->
    </style>

</resources>
--------------------------------------------------------------------test工程--------------------------------------------------------

1,清单文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.itheima.other"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="9"
        android:targetSdkVersion="17" />
    
    <instrumentation
        android:name="android.test.InstrumentationTestRunner"
        android:targetPackage="com.itheima.other" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
	   	<uses-library android:name="android.test.runner" />
        <activity
            android:name="com.itheima.other.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
2,测试类

package com.itheima.other;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.test.AndroidTestCase;

public class ProviderTest extends AndroidTestCase {
	
	public void testProvider() {
		// 获取ContentResolver对象
		ContentResolver resolver = getContext().getContentResolver();
		
		// 查询01.SQLite中的itheima.db
		Uri uri = Uri.parse("content://com.itheima.ItheimaProvider");
		resolver.query(uri, null, null, null, null);
		resolver.delete(uri, null, null);
	}
	
	public void testInsert() {
		ContentResolver resolver = getContext().getContentResolver();
		Uri uri = Uri.parse("content://com.itheima.ItheimaProvider/account");
		
		ContentValues values = new ContentValues();
		values.put("name", "ob");
		values.put("balance", 1234);
		
		Uri resultUri = resolver.insert(uri, values);
		System.out.println(resultUri);
	}
	
	public void testDelete() {
		ContentResolver resolver = getContext().getContentResolver();
		Uri uri = Uri.parse("content://com.itheima.ItheimaProvider/account/221");
		
		int count = resolver.delete(uri, null, null);
		System.out.println(count);
	}
	
	public void testUpdate() {
		ContentResolver resolver = getContext().getContentResolver();
		Uri uri = Uri.parse("content://com.itheima.ItheimaProvider/account/221");
		
		ContentValues values = new ContentValues();
		values.put("name", "update");
		values.put("balance", 300);
		
		int count = resolver.update(uri, values, null, null);
		System.out.println(count);
	}
	
	public void testQuery() {
		ContentResolver resolver = getContext().getContentResolver();
		Uri uri = Uri.parse("content://com.itheima.ItheimaProvider/account/223");
		
		Cursor c = resolver.query(uri, null, null, null, null);
		if (c.moveToNext()) {
			System.out.println(c.getString(c.getColumnIndex("name")));
			System.out.println(c.getLong(c.getColumnIndex("balance")));
		}
		c.close();
	}
	
	public void testGetType() {
		ContentResolver resolver = getContext().getContentResolver();
		System.out.println(resolver.getType(Uri.parse("content://com.itheima.ItheimaProvider/account/223")));
		System.out.println(resolver.getType(Uri.parse("content://com.itheima.ItheimaProvider/account")));
	}

}





-------------------理论----------------------------

1.1.  事务管理

Ÿ  在使用SQLite数据库时可以用SQLiteDatabase类中定义的相关方法控制事务

beginTransaction()开启事务

setTransactionSuccessful()设置事务成功标记

endTransaction()结束事务

Ÿ  endTransaction()需要放在finally中执行,否则事务只有到超时的时候才自动结束,会降低数据库并发效率

2.  内容提供者(ContentProvider)

2.1.  什么是内容提供者

Ÿ  内容提供者是Android中的四大组件之一,可以将应用中的数据对外进行共享

Ÿ  内容提供者将数据的访问方式统一,不必针对不同数据类型采取不同的访问策略

Ÿ  内容提供者将数据封装,只暴露出我们希望提供给其他程序的数据

Ÿ  内容提供者中数据更改可被监听

2.2.  创建内容提供者

Ÿ  定义类继承ContentProvider,根据需要重写内部方法

Ÿ  在清单文件的<application>节点下进行配置,<provider>标签中需要指定name和authorities属性

name为类名,包名从程序Package开始,以“.”开始

authorities:是访问Provider时的路径,要唯一

Ÿ  URI代表要操作的数据,由scheme、authorites、path三部分组成

content://cn.itcast.sqlite.provider/person

scheme:固定为content,代表访问内容提供者

authorites:<provider>节点中的authorites属性

path:程序定义的路径,可根据业务逻辑定义

2.3.  完成CRUD方法

Ÿ  当程序调用CRUD方法时会传入Uri

Ÿ  我们通过Uri判断调用者要操作的数据

可以使用工具类UriMatcher来判断Uri

addURI方法可以添加Uri

match方法可以匹配一个Uri判断其类型

Ÿ  根据业务逻辑操作数据

2.4.  访问内容提供者

Ÿ  通过Context获得ContentResolver对象

Ÿ  调用ContentResolver对象的方法即可访问内容提供者

2.5.  完成getType方法

Ÿ  如果返回数据是单条数据:vnd.android.cursor.item

Ÿ  如果返回数据是多条数据:vnd.android.cursor.dir

2.6.  监听内容提供者数据变化

Ÿ  在内容提供者中可以通知其他程序数据发生变化

通过Context的getContentResolver()方法获取ContentResolver

调用其notifyChange()方法发送数据修改通知

Ÿ  在其他程序中可以通过ContentObserver监听数据变化

通过Context的getContentResolver()方法获取ContentResolver

调用其registerContentObserver()方法指定对某个Uri注册ContentObserver

自定义ContentObserver,重写onChange()方法获取数据



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值