之前两篇文章分别介绍了OnScrollListener的实现和ContentProvider监听数据的变化,下面我们就结合者两个知识点实现一个小项目
项目需求
使用当ContentProvider监听类有数据更新时,在当前界面进行提示,并用OnScrollListener实现下拉刷新
实现效果
通过ContentProvider显示数据在界面
当监听类发生变化时
下拉刷新后显示数据
实现步骤
android_sqlite项目 定义操作标识匹配结果码继承ContentProvider类重写方法 oncreate初始化数据DatabaseHelpergetType
返回操作的类型 如果操作多条记录那么MINE类型vnd.android.cursor.dir/开头如果操作的数据只有一条记录那么MINE类型vnd.android.cursor.item/开头
insert 匹配uri插入操作监听数据变化 update 匹配多条数据还是1条数据更新操作监听数据变化 query 匹配多条数据还是1条数据查询操作 delete 匹配多条数据还是1条数据删除操作监听数据变化 android_providers项目 获取控件对象 listViewtv_tip,tv_name,tv_phone 获取内容解析器对象初始化数据 通过内容解析器对象执行查询设置adapter 注册监听器 新建class继承ContentObserver类 绑定handler对象 根据请求处理数据 重写onChange(booleab selfChange)方法发送handler的message消息 实现OnScrollListener接口并实现方法 onScrollonScrollStateChanged 初始化数据隐藏tip
重点代码:
android_sqlite项目中的UserContentProviders类
package com.example.android_sqlite.provider;
import com.example.android_sqlite.database.DatabaseHelper;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
public class UserContentProviders extends ContentProvider {
// 操作的标志
private static final String AUTHORITIE = "www.csdn.com.provider.userContentProvider";
// 定义uri解析返回的匹配码
private static final int USERCODE = 1;
private static final int USERSCODE = 2;
private static UriMatcher uriMatcher;
private String USERS_DIR = "vnd.android.cursor.dir/users";
private String USERS_ITEM = "vnd.android.cursor.item/users";
private DatabaseHelper dh;
static {
// 实例化UriMatcher对象
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
// 匹配的结果码
uriMatcher.addURI(AUTHORITIE, "users", USERSCODE);
uriMatcher.addURI(AUTHORITIE, "users/#", USERCODE);
}
/**
* 在UserContentProvider创建之后,就会被调用,当其他应用程序第一次访问contentPrivider时,
* 该ContentProvider就会被创建出来
*/
@Override
public boolean onCreate() {
dh = new DatabaseHelper(getContext());
return false;
}
/**
* URL:http://www.baidu.com/index.html http://: http协议访问网站
* www.baidu.com:域名部分 /index.html:网站资源
*
* URI:content://www.csdn.com.provider.userContentProvider/user
* content://android的ContentProvider的规定
* www.csdn.com.provider.userContentProvider:文件汇中自己配置的authorities
* user:资源部分(数据部分)当访问者需要访问不同的资源时,这个部分是动态改变.这个部分可以自己定义
*
* UriMatcher:匹配uri
*/
/**
* 查询方法
*/
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteDatabase db = dh.getWritableDatabase();
Cursor c = null;
switch ((uriMatcher.match(uri))) {
case USERCODE:// 一个条目
long id = ContentUris.parseId(uri);
c = db.query("users", projection, "userid=?", new String[] { id
+ "" }, null, null, sortOrder);
break;
case USERSCODE:
c = db.query("users", projection, selection, selectionArgs, null,
null, sortOrder);
break;
default:
throw new IllegalArgumentException("unknow URI" + uri);
}
return c;
}
/**
* 返回操作的类型 如果操作多条记录那么MINE类型vnd.android.cursor.div/开头
* 如果操作的数据只有一条记录那么MINE类型vnd.android.cursor.item/开头
*/
@Override
public String getType(Uri uri) {
String value = null;
switch (uriMatcher.match(uri)) {
case USERCODE:
value = USERS_ITEM;
break;
case USERSCODE:
value = USERS_DIR;
break;
}
return null;
}
/**
* 插入操作
*/
@Override
public Uri insert(Uri uri, ContentValues values) {
if (uriMatcher.match(uri) != USERSCODE) {
throw new IllegalArgumentException("unknow URI" + uri);
}
SQLiteDatabase db = dh.getReadableDatabase();
long rowId = db.insert("users", "username", values);
// 监听数据变化,通知注册在uri上的监听者
// 参数1:注册的uri,参数2:监听者
getContext().getContentResolver().notifyChange(uri, null);
return ContentUris.withAppendedId(uri, rowId);
}
/**
* 更新操作
*/
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
SQLiteDatabase db = dh.getWritableDatabase();
int rows = -1;
switch ((uriMatcher.match(uri))) {
case USERCODE:// 一个条目
long id = ContentUris.parseId(uri);
rows = db.update("users", values, "userid=?", new String[] { id
+ "" });
db.close();
break;
case USERSCODE:
rows = db.update("users", values, selection, selectionArgs);
break;
default:
throw new IllegalArgumentException("unknow URI" + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return rows;
}
/**
* 删除操作
*/
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
SQLiteDatabase db = dh.getWritableDatabase();
int rows = -1;
switch ((uriMatcher.match(uri))) {
case USERCODE:// 一个条目
long id = ContentUris.parseId(uri);
rows = db.delete("users", "userid=?", new String[] { id + "" });
db.close();
break;
case USERSCODE:
rows = db.delete("users", selection, selectionArgs);
break;
default:
throw new IllegalArgumentException("unknow URI" + uri);
}
getContext().getContentResolver().notifyChange(uri, null);
return rows;
}
}
android_providers项目布局文件
activity_main.xml
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
android:id="@+id/tv_tip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="15dp"
android:gravity="center"
android:textColor="#FF0000"
android:visibility="gone" />
android:id="@+id/lv_users"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/ll_title"
android:layout_marginTop="5dp" >
android:id="@+id/ll_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/tv_tip"
android:orientation="horizontal" >
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="姓名" />
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="电话" />
item_phone.xml
android:id="@+id/ll_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
android:id="@+id/tv_name"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:text="TextView"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp" />
android:id="@+id/tv_phone"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp" />
android_providers项目MainActivity
package com.example.android_providers;
import android.app.Activity;
import android.content.ContentResolver;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.widget.SimpleCursorAdapter;
import android.view.View;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ListView;
import android.widget.TextView;
public class MainActivity extends Activity implements OnScrollListener {
private ListView lv_users;
private TextView tv_tip;
private SimpleCursorAdapter adapter;
private ContentResolver contentResolver;
private static final String URL = "content://www.csdn.com.provider.userContentProvider/users";
public static final int INSERT = 1;
private boolean flag = false;
private boolean isLastRow = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv_users = (ListView) findViewById(R.id.lv_users);
tv_tip = (TextView) findViewById(R.id.tv_tip);
// 获取内容解析器对象
contentResolver = getContentResolver();
initDate();
// 注册监听器
getContentResolver().registerContentObserver(Uri.parse(URL), true,
new UserContentObserver(handler));
lv_users.setOnScrollListener(this);
}
/*
* 初始化数据
*/
private void initDate() {
// 执行查询
Cursor c = contentResolver.query(Uri.parse(URL), new String[] {
"userid as _id", "username", "userphone" }, null, null,
"userid desc");
// 控制层
adapter = new SimpleCursorAdapter(this, R.layout.item_phone, c,
new String[] { "username", "userphone" }, new int[] {
R.id.tv_name, R.id.tv_phone },
SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
lv_users.setAdapter(adapter);
}
class UserContentObserver extends ContentObserver {
private Handler handler;
public UserContentObserver(Handler handler) {
super(handler);
this.handler = handler;
}
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
// 发送空消息
handler.sendEmptyMessage(INSERT);
}
}
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case INSERT:
tv_tip.setVisibility(View.VISIBLE);
flag = true;
tv_tip.setText("有新的信息,请下拉加载......");
break;
default:
break;
}
}
};
/**
* view firstVisibleItem 第一个显示的条目的位置(下标从0开始) visibleItemContent
* 可见的条目数(包含没有显示全的) totalVisibleItem 总条数(下标从0开始)
*/
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemContent, int totalVisibleItem) {
if ((firstVisibleItem + visibleItemContent) >= totalVisibleItem
&& totalVisibleItem > 0) {
// 发送请求处理
isLastRow = true;
}
}
// 正在滚动时回调,回调2-3次,手指没抛则回调2次。scrollState = 2的这次不回调
// 回调顺序如下
// 第1次:scrollState = SCROLL_STATE_TOUCH_SCROLL(1) 正在滚动当屏幕滚动且用户使用的触碰或手指还在屏幕上
// 第2次:scrollState = SCROLL_STATE_FLING(2) 手指做了抛的动作(手指离开屏幕前,用力滑了一下)
// 第3次:scrollState = SCROLL_STATE_IDLE(0) 停止滚动
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// (有新消息)更新的时候加载数据
if (flag && scrollState == OnScrollListener.SCROLL_STATE_FLING) {
// 初始化数据
initDate();
flag = false;
tv_tip.setVisibility(View.GONE);
}
if (isLastRow && scrollState == OnScrollListener.SCROLL_STATE_FLING) {
// 数据处理
}
}
}
地址
http://blog.csdn.net/zhaoyazhi2129/article/details/30064965