码迷,mamicode.com
首页 > 数据库 > 详细

7.数据库、Contentobserver

时间:2015-11-25 16:49:37      阅读:249      评论:0      收藏:0      [点我收藏+]

标签:

群组页是程序内部维护的一个数据库,其中一张表groups,用于存放创建的群组,还有一张表thread_group,用于关联群组和系统短信数据库中的会话。
技术分享
数据库应该这样设计
技术分享技术分享
MySqliteHelper 
    1. public class MySqliteHelper extends SQLiteOpenHelper{
    2. public MySqliteHelper(Context context, String name, int version) {
    3. super(context, name, null, version);
    4. }
    5. public static final String TABLE_GROUPS = "groups";
    6. public static final String TABLE_THREAD_GROUPS = "thread_groups";
    7. @Override
    8. public void onCreate(SQLiteDatabase db) {
    9. db.execSQL("create table groups(_id integer primary key autoincrement, group_name varchar(20));");
    10. db.execSQL("create table thread_groups(_id integer primary key autoincrement, group_id integer, thread_id integer);");
    11. }
    12. @Override
    13. public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    14. // TODO Auto-generated method stub
    15. }
    16. }
DBUtils 
    1. public class DBUtils {
    2. /**
    3. * 用于更新cursor 的URI
    4. */
    5. private static final Uri uri = Uri.parse("content://www.itheima.com");
    6. private Context ctx;
    7. private MySqliteHelper sqlHelper;
    8. private DBUtils(Context ctx){
    9. this.ctx = ctx;
    10. sqlHelper = new MySqliteHelper(ctx, "heima39", 1);
    11. }
    12. private static DBUtils instance;
    13. public static synchronized DBUtils getInstance(Context ctx){
    14. if(instance == null){
    15. instance = new DBUtils(ctx);
    16. }
    17. return instance;
    18. }
    19. /**
    20. * 创建新群组
    21. * @param name 群组的名称
    22. */
    23. public void createNewGroup(String name) {
    24. SQLiteDatabase db = sqlHelper.getWritableDatabase();
    25. ContentValues values = new ContentValues();
    26. values.put("group_name", name);
    27. db.insert(MySqliteHelper.TABLE_GROUPS, "_id", values);
    28. notifyCursor();
    29. }
    30. /**
    31. * 查询所有的群组信息
    32. * @return
    33. */
    34. public Cursor getAllGroup() {
    35. SQLiteDatabase db = sqlHelper.getReadableDatabase();
    36. Cursor cursor = db.query(MySqliteHelper.TABLE_GROUPS, null, null, null, null, null, null);
    37. // android.database.sqlite.SQLiteCursor
    38. System.out.println(cursor);
    39. //为cursor 设置 通知提醒的URI
    40. cursor.setNotificationUri(ctx.getContentResolver(), uri);
    41. return cursor;
    42. }
    43. /**
    44. * 通知cursor 群组表中的内容已经发生变化
    45. * @param cursor
    46. */
    47. private void notifyCursor() {
    48. // 让内容处理者,根据URI 发出更新通知
    49. ctx.getContentResolver().notifyChange(uri, null);
    50. }
    51. /**
    52. * 通过群组ID删除群组
    53. * @param groupId
    54. */
    55. public void deleteGroupById(int groupId) {
    56. SQLiteDatabase db = sqlHelper.getWritableDatabase();
    57. db.delete(MySqliteHelper.TABLE_GROUPS, " _id = "+groupId, null);
    58. notifyCursor();
    59. }
    60. /**
    61. * 更新群组名称
    62. * @param groupId 群组的ID
    63. * @param name 群组的新名
    64. */
    65. public void updateGroupById(int groupId, String name) {
    66. SQLiteDatabase db = sqlHelper.getWritableDatabase();
    67. ContentValues values = new ContentValues();
    68. values.put("group_name", name);
    69. db.update(MySqliteHelper.TABLE_GROUPS, values, " _id = "+groupId , null);
    70. notifyCursor();
    71. }
    72. /**
    73. * 将会话ID和群组ID 插入到会话群组关系 表中
    74. * @param threadId
    75. * @param groupId
    76. */
    77. public void insertThradIdAndGroupId(int threadId, int groupId) {
    78. SQLiteDatabase db = sqlHelper.getWritableDatabase();
    79. ContentValues values = new ContentValues();
    80. values.put("thread_id", threadId);
    81. values.put("group_id", groupId);
    82. db.insert(MySqliteHelper.TABLE_THREAD_GROUPS,null, values);
    83. }
    84. /**
    85. * 返回所有的指定群组ID的会话信息
    86. * @param groupId
    87. * @return
    88. */
    89. public Cursor getAllThreadIdByGroupId(int groupId) {
    90. SQLiteDatabase db = sqlHelper.getReadableDatabase();
    91. Cursor cursor = db.query(MySqliteHelper.TABLE_THREAD_GROUPS, null, " group_id = "+groupId, null, null, null, null);
    92. return cursor;
    93. }
    94. }
在activity中不需要做任何操作,当数据库发生变化list条目也变化了,前提必须是CursorAdapter
源码:
curosr 注册监听:
* cursor.setNotificationUri(ctx.getContentResolver(), uri);
* SQLiteCursor --> AbstractWindowedCursor  --> AbstractCursor 
*  在AbstractCursor类中:
public void setNotificationUri(ContentResolver cr, Uri notifyUri) {
mNotifyUri = notifyUri;
mContentResolver = cr;
 
mSelfObserver = new SelfContentObserver(this);
// 将uri 和 mSelfObserver 在  mContentResolver 中注册 
mContentResolver.registerContentObserver(mNotifyUri, true, mSelfObserver);

}
}

发出通知:
ctx.getContentResolver().notifyChange(uri, null);
* 在 ContentResolver中发出通知:
notifyChange(uri, observer, true /* sync to network */);
*结论: 根据uri 找到 监听此URI 的Contentobserver ,即  AbstractCursor 类中的 mSelfObserver 然后,执行,mSelfObserver 中 onChange方法
* 那么 cursor 中的内容观察者执行onChange方法 时,如何刷新页面:

* CursorAdapter  init方法中为cursor注册了二个监听:
c.registerContentObserver(mChangeObserver); // 内容观察者
c.registerDataSetObserver(mDataSetObserver); // 数据观察者
* 当Contentobserver 根据URI 发送更新通知时,执行cursor的 内容观察者即:
* mChangeObserver.onChange()方法 :
   private class ChangeObserver extends ContentObserver {
public void onChange(boolean selfChange) {
onContentChanged();
}
}
* 在 onContentChanged方法 中 执行curosr.requery:
 protected void onContentChanged() {
...
mDataValid = mCursor.requery();
}
* 此时,cursor ,实际对象是 SQLiteCursor ,就执行 SQLiteCursor 中的requery方法 ,
* 在SQLiteCursor 中的requery方法中:
* 重新查询数据:
* 执行数据观察者的notify方法 :mDataSetObservable.notifyChanged();
* 即执行观察者的onChanged方法: observer.onChanged();
* CursorAdapter中已经为cursor 注册了一个数据观察者: mDataSetObserver 
* 当 mDataSetObserver 执行onChanged 方法时:
  private class MyDataSetObserver extends DataSetObserver {
public void onChanged() {
mDataValid = true;
notifyDataSetChanged(); // 刷新了listView的数据 
}

GroupUI 
群组创建后,在会话页,长按某一个会话添加到群组中
技术分享
    1. public class GroupUI extends ListActivity implements OnItemLongClickListener, OnItemClickListener{
    2. private ListView listView;
    3. private Context ctx;
    4. @Override
    5. protected void onCreate(Bundle savedInstanceState) {
    6. super.onCreate(savedInstanceState);
    7. ctx = this;
    8. listView = getListView();
    9. adapter = new GropListAdapter(this, null);
    10. listView.setAdapter(adapter);
    11. listView.setOnItemLongClickListener(this);
    12. listView.setOnItemClickListener(this);
    13. prepareData();
    14. }
    15. private void prepareData() {
    16. DBUtils dbu = DBUtils.getInstance(ctx);
    17. Cursor cursor = dbu.getAllGroup();
    18. adapter.changeCursor(cursor);
    19. }
    20. private GropListAdapter adapter;
    21. class GropListAdapter extends CursorAdapter{
    22. public GropListAdapter(Context context, Cursor c) {
    23. super(context, c);
    24. }
    25. @Override
    26. public View newView(Context context, Cursor cursor, ViewGroup parent) {
    27. View view = View.inflate(context, R.layout.list_item_group, null);
    28. TextView name = (TextView) view.findViewById(R.id.tv_name_group);
    29. view.setTag(name);
    30. return view;
    31. }
    32. @Override
    33. public void bindView(View view, Context context, Cursor cursor) {
    34. TextView name = (TextView) view.getTag();
    35. name.setText(cursor.getString(cursor.getColumnIndex("group_name")));
    36. }
    37. }
    38. @Override
    39. /**
    40. * 创建菜单
    41. */
    42. public boolean onCreateOptionsMenu(Menu menu) {
    43. // 将 资料ID对应的文件转换为 菜单条目 ,并添加至 menu 中
    44. getMenuInflater().inflate(R.menu.activity_group, menu);
    45. return true;
    46. }
    47. @Override
    48. /**
    49. * 响应菜单的点击事件
    50. */
    51. public boolean onOptionsItemSelected(MenuItem item) {
    52. switch (item.getItemId()) {
    53. case R.id.menu_new_group:
    54. showCreateGroupDialog();
    55. break;
    56. }
    57. return true;
    58. }
    59. private AlertDialog dialog;
    60. /**
    61. * 显示新建群组对话框
    62. */
    63. private void showCreateGroupDialog() {
    64. AlertDialog.Builder adb =new AlertDialog.Builder(ctx);
    65. dialog = adb.create();
    66. View view = View.inflate(ctx, R.layout.dialog_new_group, null);
    67. final EditText etInputName = (EditText) view.findViewById(R.id.et_input_new_group);
    68. Button btnOk = (Button) view.findViewById(R.id.btn_ok);
    69. btnOk.setOnClickListener(new OnClickListener() {
    70. @Override
    71. public void onClick(View v) {
    72. String name = etInputName.getText().toString();
    73. if(TextUtils.isEmpty(name)){
    74. Toast.makeText(ctx, "请输入群组名称", 0).show();
    75. return ;
    76. }
    77. // 将群组名称保存至数据库
    78. DBUtils dbu = DBUtils.getInstance(ctx);
    79. dbu.createNewGroup(name);
    80. dialog.dismiss();
    81. }
    82. });
    83. dialog.setView(view,0,0,0,0);
    84. dialog.show();
    85. }
    86. @Override
    87. /**
    88. * 响应listview条目的长按事件
    89. */
    90. public boolean onItemLongClick(AdapterView<?> parent, View view,
    91. int position, long id) {
    92. showEditGroupDialog(position);
    93. return true;
    94. }
    95. /**
    96. * 显示编辑群组对话框
    97. * @param position
    98. */
    99. private void showEditGroupDialog(final int position) {
    100. AlertDialog.Builder adb = new AlertDialog.Builder(ctx);
    101. String items[]=new String[]{"编辑","删除"};
    102. adb.setItems(items, new DialogInterface.OnClickListener() {
    103. @Override
    104. /**
    105. * which 是点击的条目的位置
    106. */
    107. public void onClick(DialogInterface dialog, int which) {
    108. if(which == 0){ // “编辑”
    109. showUpdateGroupDialog(position);
    110. }else{ // 删除
    111. showConfirmDeleteDialog(position);
    112. }
    113. }
    114. });
    115. adb.show();
    116. }
    117. /**
    118. * 显示确认删除的对话框
    119. * @param position
    120. */
    121. protected void showConfirmDeleteDialog(final int position) {
    122. AlertDialog.Builder adb = new AlertDialog.Builder(ctx);
    123. adb.setTitle("删除群组");
    124. adb.setMessage("确定要删除这个群吗?");
    125. adb.setNegativeButton("确定", new DialogInterface.OnClickListener() {
    126. @Override
    127. public void onClick(DialogInterface dialog, int which) {
    128. // 删除对应的群组
    129. DBUtils dbu = DBUtils.getInstance(ctx);
    130. Cursor cursor = adapter.getCursor();
    131. cursor.moveToPosition(position);
    132. int groupId = cursor.getInt(0); // 获得第0列的值,即,_id 这一列的值
    133. dbu.deleteGroupById(groupId);
    134. dialog.dismiss();
    135. }
    136. });
    137. adb.setPositiveButton("取消", null);
    138. adb.show();
    139. }
    140. /**
    141. * 显示更新群组的对话框
    142. * @param position
    143. */
    144. protected void showUpdateGroupDialog(final int position) {
    145. AlertDialog.Builder adb =new AlertDialog.Builder(ctx);
    146. dialog = adb.create();
    147. View view = View.inflate(ctx, R.layout.dialog_new_group, null);
    148. TextView title = (TextView) view.findViewById(R.id.tv_title_dialog);
    149. title.setText("更新群组名称");
    150. final EditText etInputName = (EditText) view.findViewById(R.id.et_input_new_group);
    151. Button btnOk = (Button) view.findViewById(R.id.btn_ok);
    152. btnOk.setOnClickListener(new OnClickListener() {
    153. @Override
    154. public void onClick(View v) {
    155. String name = etInputName.getText().toString();
    156. if(TextUtils.isEmpty(name)){
    157. Toast.makeText(ctx, "请输入群组名称", 0).show();
    158. return ;
    159. }
    160. // 将群组名称保存至数据库
    161. DBUtils dbu = DBUtils.getInstance(ctx);
    162. Cursor cursor = adapter.getCursor();
    163. cursor.moveToPosition(position);
    164. int groupId = cursor.getInt(0); // 获得群组ID
    165. dbu.updateGroupById(groupId,name);
    166. dialog.dismiss();
    167. }
    168. });
    169. dialog.setView(view,0,0,0,0);
    170. dialog.show();
    171. }
    172. @Override
    173. /**
    174. * 响应listview条目点击事件
    175. */
    176. public void onItemClick(AdapterView<?> parent, View view, int position,
    177. long id) {
    178. Cursor cursor = adapter.getCursor();
    179. cursor.moveToPosition(position);
    180. int groupId = cursor.getInt(0); // 返回群组ID
    181. DBUtils dbu =DBUtils.getInstance(ctx);
    182. Cursor cursor2 = dbu.getAllThreadIdByGroupId(groupId);
    183. if(cursor2.getCount() == 0){ // 该群组没有人
    184. Toast.makeText(ctx, "该群还没有人,快回点人气吧", 0).show();
    185. }else{
    186. // 如果有人的话,希望能过cursor2 拼凑出如: thread_id in (1,2);
    187. String subSql = convertCursor2Str(cursor2);
    188. System.out.println("subSql"+subSql);
    189. Intent intent = new Intent(this,ConversationUI.class);
    190. intent.putExtra("subSql", subSql);
    191. startActivity(intent);
    192. }
    193. }
    194. /**
    195. * 根据cursor中的内容,拼凑出 如 thread_id in (1,2); 的字符串
    196. * @param cursor2
    197. * @return
    198. */
    199. private String convertCursor2Str(Cursor cursor) {
    200. cursor.moveToPosition(-1);
    201. StringBuilder sb=new StringBuilder(" thread_id in ( ");
    202. while(cursor.moveToNext()){
    203. String threadId = cursor.getString(cursor.getColumnIndex("thread_id"));
    204. sb.append(threadId+","); // thread_id in (1,
    205. }
    206. // thread_id in (1,2,3,4,
    207. sb.replace(sb.lastIndexOf(","), sb.length(), ")");
    208. return sb.toString();
    209. }
    210. }





7.数据库、Contentobserver

标签:

原文地址:http://www.cnblogs.com/liuyu0529/p/4994973.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!