文档章节

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

f
 flyqilong
发布于 2016/02/21 21:30
字数 1500
阅读 31
收藏 0
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" />


© 著作权归作者所有

f
粉丝 3
博文 93
码字总数 53900
作品 0
Android工程师
私信 提问
android JNI C代码对sdcard中文件的操作

所有操作除路径不同其它全部相同,如:fopen, fclose, fread ... - 别忘记把权限加上,如下: <uses-permission android:name="android.permission.WRITEEXTERNALSTORAGE"/> <uses-permissi......

fcsong000833
2013/09/06
0
0
树莓派玩机笔记(二)

每次调试树莓派都需要连接电视HDMI,很不方便。东哥决定去网上淘一根USB转TTL线,直接把屏幕,键盘,鼠标,都省了,直接用串口登陆,巴适得很啊哈哈。 这是东哥购买USB转TTL线淘宝店铺地址,...

w2630460
2014/04/07
0
0
轻松时刻–在pcDuino上玩小游戏

今天我们要放松一下,用pcDuino来玩一下小游戏了。 大家都知道pcDuino是可以兼容Ubuntu和Android两种系统的。 我们给大家分享的游戏就是Android系统下完成的,相信大家也玩过Android系统的手...

pc朵拉
2013/07/02
0
0
android使用MediaRecorder实现录音

有四个按钮,分别是“录音”、“停止”、“播放”、“删除”。如图1所示。 图1:录音机的界面 MediaRecorder的生命周期 MediaRecorder可以用来录制音频或视频。它具有以下几个状态: Initial:...

苍海一粟
2011/11/15
0
2
NIOS2随笔——SD卡之SPI操作

1. 概述 SD卡(Secure Digital Memory Card),基于MMC发展而来,被广泛应用于数码产品中。 SD卡可分为3类:SD卡(0~2G)、SDHC卡(2~32G)、SDXC卡(32G~2T)。 SD卡有9个PIN,支持SPI和SDIO模式: ...

shugenyin
2016/10/29
0
0

没有更多内容

加载失败,请刷新页面

加载更多

零基础学画画应该从哪开始?

零基础学画画应该从哪开始?一种是从小有兴趣,喜欢涂鸦,喜欢将自己的创意和想法表现出来;另一种是长大后审美提高,开始对绘画艺术感兴趣,从而开始从零基础学起。 推荐大家可以搜一下:轻微...

设绘嗨
23分钟前
2
0
你编写的程序高效、优雅吗?阿里架构师教你编写高效优雅Java程序

面向对象 构造器参数太多怎么办? 用 builder 模式,用在 1、5 个或者 5 个以上的成员变量 2、参数不多,但是在未来,参数会增加 Builder 模式: 属于对象的创建模式,一般有 1. 抽象建造者:...

kx33389
27分钟前
2
0
PDF 文档操作Java类库Spire.PDF for Java v2.7.6发布上线!| 附下载

Spire.PDF for Java是一款专门对 PDF 文档进行操作的 Java 类库。该类库的主要功能在于帮助开发人员在 Java 应用程序(J2SE和J2EE)中生成 PDF 文档和操作现有 PDF 文档,并且运行环境无需安...

mnrssj
36分钟前
1
0
初探云原生应用管理(二): 为什么你必须尽快转向 Helm v3

在研究了一番“开放云原生应用中心(AppHub)”之后,程序员小张似乎已经明白了“云原生应用”到底是怎么一回事情。 “不就是 Helm 嘛!” 这不,小张这就准备把自己开发多年的“图书馆管理系...

zhaowei121
39分钟前
0
0
「工具」三分钟了解一款思维导图工具:XMind Zen

一款非常实用的商业思维导图软件,融合艺术与创造力。致力于高效的可视化思维,强调软件的跨平台使用,帮助用户提高生产效率。 相关信息 · 操作系统:macOS / Windows / Linux · 官方网站:...

极光推送
41分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部