有几个微博邀请了,放出来和大家共享
http://t.qq.com/invite/8e2677413d916d4a4199
http://t.qq.com/invite/bfafba73902f66d233bb
http://t.qq.com/invite/cc0c589cc0fe75fdc887
http://t.qq.com/invite/e2a0f6e9b9e29c7364d1
http://t.qq.com/invite/80bde62720dfb339d8d1
http://t.qq.com/invite/bc9add9d6590dcead05d
http://t.qq.com/invite/e72de68883edb6197cc7
No tags
最重要的是态度,需要主动阅读
1. 检视阅读的方法
1) 看书名和序
2) 看目录
3) 看索引
4) 看作者介绍
5) 挑几个主题相关的篇章看看
6) 随便翻翻,翻完全书,
7) 看最后2,3页
2. 主动阅读的四个基本问题
1) 总体来说,这本书在说什么?
2) 从细部讲,作者又提出哪些主要想法/
3) 这本书说的对,部分对还是全部对,我是否能接受?
4) 这本书能给我带来什么?
3. 做笔记的方法
1) 画底线
2) 在空白处做星号
3) 在空白处留下其他相关的页码,用Cf
4. 分析阅读的方法
1) 采用略读或粗读全文的方法,为分析阅读做准备
2) 分析阅读的原则:
1) 分类
2) 简短描述这本书讲了什么
3) 将重要部分拟大纲
4) 知道作者想要解决什么问题
5) 注意关键字
6) 注意重要的句子
7) 确定作者的观点,根据文章内容重新整理出来
确定哪些问题在文章中已被解决,哪些未被解决
9) 不要随意评论
No tags
刚开始看Android NotePad中的ContentProvider的实现时,看的云里雾里,但自己模仿写过一个后,才发现也就这么一回事,就是实现公用的增删改查。下面将需要实现的方法做一个简单的回顾:
1.一个ContentProvider可以实现对多个数据表的操作,但每一个数据表都需要有一个独立URI,也必须有一个独立的类型。URI是其他应用访问这个数据入口,比如:
content://com.chenyc.timeaccount.provider/eventtypes/id
它包括4部分,content://就是固定的头部,com.chenyc.timeaccount.provider部分需要一个唯一的字符串,一般就用ContentProiver类所在的包名,eventtypes部分一般是指在这个ContentProvider下,你需要操作那种类型的数据,一般可以用表名来表示,id部分是指具体操作数据的_id,如果查询某一条数据,则id部分就是其在数据库中的_id字段的值。
每个数据表需要有一个独立的数据类型,需要在getType(Uri uri)中实现,返回一个唯一的字符串即可,比如:vnd.chenyc.cursor.dir/vnd.account.eventtype
2.query方法,查询作为最常用的方法,实现也很简单,projection参数代表要查那些列,selection是where条件部分,selectionArgs是where条件部分参数的值,sortOrder指排序,switch部分判断是查一条数据,还是查一个list,然后根据情况进行查询
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
switch (sUriMatcher.match(uri)) {
case EVENT_TYPES:
qb.setTables(EVENT_TYPE_TABLE_NAME);
qb.setProjectionMap(sEventTypesProjectionMap);
break;
case EVENT_TYPE_ID:
qb.setTables(EVENT_TYPE_TABLE_NAME);
qb.setProjectionMap(sEventTypesProjectionMap);
qb.appendWhere(EventTypeAdapter.KEY_ROWID + "="
+ uri.getPathSegments().get(1));
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
SQLiteDatabase db = mDbHelper.getReadableDatabase();
Cursor c = qb.query(db, projection, selection, selectionArgs, null,
null, sortOrder);
c.setNotificationUri(getContext().getContentResolver(), uri);
return c;
}
3.delete方法,处理方式也跟查询差不多,也分删一个和删一批
public int delete(Uri uri, String where, String[] whereArgs) {
SQLiteDatabase db = mDbHelper.getWritableDatabase();
int count;
switch (sUriMatcher.match(uri)) {
case EVENT_TYPES:
count = db.delete(EVENT_TYPE_TABLE_NAME, where, whereArgs);
break;
case EVENT_TYPE_ID:
String id = uri.getPathSegments().get(1);
count = db.delete(EVENT_TYPE_TABLE_NAME,
EventTypeAdapter.KEY_ROWID
+ "="
+ id
+ (!TextUtils.isEmpty(where) ? " AND (" + where
+ ')' : ""), whereArgs);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
4.insert方法,插入成功后需要返回这条记录的URI
public Uri insert(Uri uri, ContentValues initialValues) {
SQLiteDatabase db = mDbHelper.getWritableDatabase();
long rowId = 0;
Uri contentUri;
switch (sUriMatcher.match(uri)) {
case EVENT_TYPES:
rowId = db.insert(EVENT_TYPE_TABLE_NAME, "null", initialValues);
contentUri = TimeAccount.EVENT_TYPE_CONTENT_URI;
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
if (rowId > 0) {
Uri returnUri = ContentUris.withAppendedId(contentUri, rowId);
getContext().getContentResolver().notifyChange(returnUri, null);
return returnUri;
}
throw new SQLException("Failed to insert row into " + uri);
}
5.update方法,更新成功后需要返回修改的记录数
public int update(Uri uri, ContentValues values, String where,
String[] whereArgs) {
SQLiteDatabase db = mDbHelper.getWritableDatabase();
String id;
int count;
switch (sUriMatcher.match(uri)) {
case EVENT_TYPES:
count = db.update(EVENT_TYPE_TABLE_NAME, values, where, whereArgs);
break;
case EVENT_TYPE_ID:
id = uri.getPathSegments().get(1);
count = db.update(EVENT_TYPE_TABLE_NAME, values,
EventTypeAdapter.KEY_ROWID
+ "="
+ id
+ (!TextUtils.isEmpty(where) ? " AND (" + where
+ ')' : ""), whereArgs);
break;
default:
throw new IllegalArgumentException("Unknown URI " + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return count;
}
SimpleCursorAdapter可以把我们从Array或数据库中取出的数据绑定的ListView或其他的组件,这个很好用,但有时候有些View,SimpleCursorAdapter并不能直接绑定,需要自己去实现它的setViewBinder方法,下面是我利用SimpleCursorAdapter绑定RatingBar的例子:
SimpleCursorAdapter timeItems = new SimpleCursorAdapter(this,
R.layout.timeitem_row, timeItemsCursor, from, to);
timeItems.setViewBinder(new SimpleCursorAdapter.ViewBinder(){
@Override
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
int rateIndex = cursor.getColumnIndex("rate");
if(columnIndex == rateIndex)
{
RatingBar ratingBar = (RatingBar)view;
ratingBar.setRating(cursor.getInt(rateIndex));
return true;
}
return false;
}
});
1.在Android中编写Service,需要继承android.app.Service,覆盖其onCreate()和onStart(Intent intent, int startId)方法即可,onCreate方法只在service创建时调用,onStart方法每次都会调用。
2.在Service中不能直接访问数据库,只能通过ContentResolver访问,如果访问自己的数据,需要继承ContentProvider并实现其方法,才能被ContentResolver访问,以下使用ContentResolver的方法:
mCursor = getContentResolver().query(
Uri.withAppendedPath(
TimeAccount.EVENT_TYPE_CONTENT_URI, "/" + pid),
new String[] { "name" }, null, null, null);
3.在Service中可以直接使用本应用的SharePreferences,我本来以为本来这个也用数据库一样,需要写成ContentProvider,没想到可以直接使用;例如:
sharePreferences = PreferenceManager.getDefaultSharedPreferences(this);
INTERVAL = Integer.valueOf(sharePreferences.getString(
"sync_interval_list", "60"));
4.Service有两种形式,一种是生命周期依赖于所启动的应用,就是BInd形式,通过bindService启动;另一种就是不依赖启动的应用,在应用已被操作系统干掉后,服务还会一直存在,通过startService启动。例如:
Intent serviceIntent = new Intent();
serviceIntent.setAction("com.chenyc.timeaccount.sync.SYNC_SERVICE");
context.startService(serviceIntent);
5.自己编写的Service,需要在AndroidManifest.xml中注册,例如:
<service android:name="com.chenyc.timeaccount.sync.SyncService">
<intent-filter>
<action android:name="com.chenyc.timeaccount.sync.SYNC_SERVICE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
6.如果想在开机时就启动Service,需要写一个BroadcastReceiver接收BOOT_COMPLETED消息,系统启动完成后会发出这个消息;编写的BroadcastReceiver也需要在AndroidManifest.xml中注册。
IntentReceiver类接收消息,并启动服务:
public class IntentReceiver extends BroadcastReceiver {
public void onReceive(Context context, Intent intent) {
Intent serviceIntent = new Intent();
serviceIntent.setAction("com.chenyc.timeaccount.sync.SYNC_SERVICE");
context.startService(serviceIntent);
}}
在AndroidManifest.xml中注册:
<receiver android:name="com.chenyc.timeaccount.sync.IntentReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.HOME" />
</intent-filter>
</receiver>



