您的位置:首页 > 数据库

AsycTaskLoader:数据库是从外面写好拖进SD卡的(17)

2016-02-21 00:00 288 查看
摘要: 使用异步加载器要继承AsyncTaskLoader这个类,我这里加进了上下文菜单的删除修改功能,如果只是了解AsycTaskLoader可以删了这些代码,我这里用的数据是自己用第三方软件创建的数据库,这个是用第三方软件手动建的数据库,然后拖进SD卡的形式来读取数据,封装了一个类

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);// 这个方法比上面的那个好:有两个好处,实际调用一下方法:
// 1、调用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" />
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: