public class MainActivity extends FragmentActivity implements LoaderCallbacks<Cursor> { private ListView listview; private static SimpleCursorAdapter adapter; private LoaderManager loaderManager;// 加載管理器 private static MySQLiteDatabaseUtils databaseUtils;// 數據庫工具類對象聲明 // private static Cursor cursor;//不定義去全局,適配器開始給個null,由於下面異步加載能夠返回一cursor @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); listview = (ListView) this.findViewById(R.id.listView_main_titlelist); databaseUtils = new MySQLiteDatabaseUtils(); // 加載管理器用getSupportLoaderManager()方法時要將Activity改成繼承FragmentActivity,版本兼容額問題 loaderManager = getSupportLoaderManager(); // initLoader(arg0, arg1, arg2); // 第一個參數:加載器標誌,能夠隨便寫如1..第二個是:Bundle,用來傳數據,沒有就寫null // 第三個參數是:實現的LoaderCallbacks接口對象,即this // 初始化加載器,若是當前沒有加載器,調用onCreateLoader()方法進行建立 loaderManager.initLoader(1, null, this); adapter = new SimpleCursorAdapter(this, R.layout.item_listview, null, new String[] { "sname", "score" }, new int[] { R.id.text_item_sname, R.id.text_item_score }, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER); listview.setAdapter(adapter); registerForContextMenu(listview); } // 上下文菜單 @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { menu.add(menu.NONE, 1, menu.NONE, "刪除"); menu.add(menu.NONE, 2, menu.NONE, "修改"); AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo; long id = adapter.getItemId(info.position); menu.setHeaderTitle(id + ""); menu.setHeaderIcon(R.drawable.ic_launcher); super.onCreateContextMenu(menu, v, menuInfo); } //上下文事件 @Override public boolean onContextItemSelected(MenuItem item) { AdapterContextMenuInfo info = (AdapterContextMenuInfo) item .getMenuInfo(); final long id = adapter.getItemId(info.position); switch (item.getItemId()) { case 1: String sql = "delete from studentinfo where sid=?"; boolean result = databaseUtils.executeData(sql, new String[] { id + "" }); if (result) { // 更新數據用異步管理器進行數據更新 Toast.makeText(this, "刪除成功!", 100).show(); loaderManager.restartLoader(1, null, this); } else { Toast.makeText(this, "刪除失敗!", 100).show(); } break; case 2: AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("修改數據"); builder.setIcon(R.drawable.ic_launcher); View view = getLayoutInflater().inflate( R.layout.dialoug_update_main, null); TextView text_id = (TextView) view .findViewById(R.id.text_dialog_id); final EditText edit_name = (EditText) view .findViewById(R.id.editText_dialog_name); final EditText edit_score = (EditText) view .findViewById(R.id.editText_dialog_score); builder.setView(view); String sql2 = "select * from studentinfo where sid=?"; Cursor cursor = databaseUtils.selectCursor(sql2, new String[] { id + "" }); cursor.moveToFirst(); text_id.setText(id + ""); edit_name.setText(cursor.getString(cursor.getColumnIndex("sname"))); edit_score .setText(cursor.getString(cursor.getColumnIndex("score"))); cursor.close(); builder.setPositiveButton("肯定", new OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { String sname = edit_name.getText().toString(); String score = edit_score.getText().toString(); String sql = "update studentinfo set sname=?,score=?where sid=?"; boolean result = databaseUtils.executeData(sql, new Object[] { sname, score, id }); if (result) { // 更新數據用異步管理器進行數據更新 Toast.makeText(MainActivity.this, "修改爲功!", 100).show(); loaderManager.restartLoader(1, null, MainActivity.this); } else { Toast.makeText(MainActivity.this, "修改失敗!", 100).show(); } } }); builder.setNegativeButton("取消", null); builder.show(); break; } return super.onContextItemSelected(item); } // 注意:若是異步加載是一個內部類,則要定義爲靜態類,不然會報錯,固然在外部定義就不會錯,裏面用到的也要變爲靜態 // 使用異步加載要繼承AsyncTaskLoader這個類,重寫裏面的方法 static class MyAsyncTaskLoader extends AsyncTaskLoader<Cursor> { // AsyncTaskLoader<Object>裏面的參數能夠是Cursor或list集合等,通常是Cursor // 它沒有無參構造方法,因此要一個構造方法,傳入上下文 public MyAsyncTaskLoader(Context context) { super(context); } @Override protected void onStartLoading() { // 開始加載,在主線程運行 super.onStartLoading(); Log.i("MainActivity", "onStartLoading測試在那個線程運行" + Thread.currentThread().getName()); forceLoad();// 這裏開始加載什麼都沒有作,可是建議寫上forceLoad()這個方法 // 即一次調用下一個即將調用的方法(強制加載) } @Override // 加載器開啓後,開啓子線程進行數據加載操做 public Cursor loadInBackground() { // 記得若是是用遊標適配器的時候查詢語句的id要把本身的sid轉換成下劃線的_id至關於(sid as _id) String sql = "select sid _id,sname,score from studentinfo"; Cursor cursor = databaseUtils.selectCursor(sql, null); Log.i("MainActivity", "loadInBackground測試在那個線程運行" + Thread.currentThread().getName()); return cursor; } @Override public void deliverResult(Cursor data) { // 在主線程運行 super.deliverResult(data); Log.i("MainActivity", "deliverResult測試在那個線程運行" + Thread.currentThread().getName()); // 交換新舊cursor交換後實際還有調用notifyDataSetChanged() adapter.swapCursor(data);// 這個方法沒有關閉遊標,要想關閉就要返回一個遊標才能關閉 // adapter.changeCursor(data);// 這個方法比上面的那個好:有兩個好處,實際調用一下方法: // 一、調用swapCursor(data)並進行notifyDataSetChanged()2.關閉舊遊標old_cursor.close(); } } // AsyncTaskLoader第一步:要實現 LoaderCallbacks<Cursor>接口,並重寫裏面的三個方法 @Override // 返回的是Loader因此要自定義loader類,有兩種:AsyncTaskLoader和CursorLoader,這裏選擇前一種建立 // 在主線程運行 public Loader<Cursor> onCreateLoader(int id, Bundle bundle) { return new MyAsyncTaskLoader(this); } @Override // 在主線程運行 public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { // adapter.swapCursor(cursor);// 執行完後能夠再交換,即執行完更新數據,這裏寫交換也行 } @Override // 在主線程運行 public void onLoaderReset(Loader<Cursor> loader) { adapter.swapCursor(null);// 執行完後能夠賦空,替換掉 } } //數據庫操做的封裝類 public class MySQLiteDatabaseUtils { private static final String dbPtah = Environment .getExternalStorageDirectory() + File.separator + "student.db";//數據庫名稱,這個是用第三方軟件手動建的數據庫,而後拖進SD卡的形式 private SQLiteDatabase db; /** * 創建數據庫鏈接的構造方法 */ public MySQLiteDatabaseUtils() { db = SQLiteDatabase.openDatabase(dbPtah, null, SQLiteDatabase.OPEN_READWRITE); } /** * 查詢方法一:返回的是遊標 * * @param sql * @param selectionArgs * @return */ public Cursor selectCursor(String sql, String[] selectionArgs) { Cursor cursor = db.rawQuery(sql, selectionArgs); return cursor; } /** * 查詢方法二:返回的是lsit集合 * * @param sql * @param selectionArgs * @return */ public List<Map<String, String>> selectList(String sql, String[] selectionArgs) { Cursor cursor = db.rawQuery(sql, selectionArgs); return cursorToList(cursor); } /** * 封裝遊標數據到List * * @param cursor * @return */ public List<Map<String, String>> cursorToList(Cursor cursor) { List<Map<String, String>> list = new ArrayList<Map<String, String>>(); while (cursor.moveToNext()) {// 循環的是每一行數據 Map<String, String> map = new HashMap<String, String>(); for (int i = 0; i < cursor.getColumnCount(); i++) {// 這個循環的是每一行的列數 map.put(cursor.getColumnName(i), cursor.getString(i));// 鍵:key:存儲每一行的字段,value:值就是內容 } list.add(map); } cursor.close(); return list; } /** * 增刪查的方法 * * @param sql * @param bindArgs * :是 sql語句中要綁定(佔位符)的參數值 * @return */ public boolean executeData(String sql, Object[] bindArgs) { try { if (bindArgs == null) { db.execSQL(sql); } else { db.execSQL(sql, bindArgs); } return true; } catch (SQLException e) { e.printStackTrace(); Log.i("MainActivity", "數據錯誤!!"); return false; } } // 關閉時銷燬db public void destroy() { if (db != null) { db.close(); } } } //主佈局 <ListView android:id="@+id/listView_main_titlelist" android:layout_width="match_parent" android:layout_height="match_parent" > </ListView> //listview中的自定義佈局 <TextView android:id="@+id/text_item_sname" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TextView" /> <TextView android:id="@+id/text_item_score" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TextView" />