赵雅智_android实例_当监听类有数据更新时下拉刷新

之前两篇文章分别介绍了OnScrollListener的实现和ContentProvider监听数据的变化,下面我们就结合者两个知识点实现一个小项目

项目需求

使用当ContentProvider监听类有数据更新时,在当前界面进行提示,并用OnScrollListener实现下拉刷新

实现效果

通过ContentProvider显示数据在界面

当监听类发生变化时

下拉刷新后显示数据

实现步骤

  • android_sqlite项目

    • 定义操作标识
    • 匹配结果码
    • 继承ContentProvider类重写方法
      • oncreate初始化数据DatabaseHelper
      • getType 
        • 返回操作的类型 如果操作多条记录那么MINE类型vnd.android.cursor.dir/开头
        • 如果操作的数据只有一条记录那么MINE类型vnd.android.cursor.item/开头
      • insert
        • 匹配uri
        • 插入操作
        • 监听数据变化
      • update
        • 匹配多条数据还是1条数据
        • 更新操作
        • 监听数据变化
      • query
        • 匹配多条数据还是1条数据
        • 查询操作
    • delete
      • 匹配多条数据还是1条数据
      • 删除操作
      • 监听数据变化
  • android_providers项目
    • 获取控件对象

      • listView
      • tv_tip,tv_name,tv_phone
    • 获取内容解析器对象
    • 初始化数据
      • 通过内容解析器对象执行查询
      • 设置adapter
    • 注册监听器
      • 新建class继承ContentObserver类

        • 绑定handler对象

          • 根据请求处理数据
        • 重写onChange(booleab selfChange)方法发送handler的message消息
    • 实现OnScrollListener接口并实现方法
      • onScroll
      • onScrollStateChanged
        • 初始化数据
        • 隐藏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

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        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" >
    
        <TextView
            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" />
    
        <ListView
            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" >
        </ListView>
    
        <LinearLayout
            android:id="@+id/ll_title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/tv_tip"
            android:orientation="horizontal" >
    
            <TextView
                android:layout_width="100dp"
                android:layout_height="wrap_content"
                android:text="姓名" />
    
            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="电话" />
        </LinearLayout>
    
    </RelativeLayout>

    item_phone.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/ll_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >
    
        <TextView
            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" />
    
        <TextView
            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" />
    
    </LinearLayout>

    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

  • 赵雅智_android实例_当监听类有数据更新时下拉刷新,布布扣,bubuko.com

    时间: 2024-12-26 06:08:29

    赵雅智_android实例_当监听类有数据更新时下拉刷新的相关文章

    赵雅智_Android案例_刮刮乐

    实现效果 主要代码 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" > <I

    赵雅智_Android短信发送器

    注意要点: 1)必须要在AndroidManifest.xml中添加发送短信权限<uses-permission android:name="android.permission.SEND_SMS" /> 设置视图:setContentView(R.layout.布局xml文件); 2)查找控件:findViewById(R.id.控件id); 3)监听按钮事件:控件.setOnClickListener(this),实现OnClickListener接口 4)获取edit

    赵雅智_android http get请求

    <!-- 添加网络访问权限 --> <uses-permission android:name="android.permission.INTERNET"/> 布局文件 activity_login.xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content&q

    赵雅智_android使用adb命令详解附图

    adb是一个客户端-服务器端程序,其中客户端是你用来操作的电脑,服务器端是android设备 我们除了用可视化窗口中操作也可以采用cmd命令行进行操作. 在开始菜单的搜索栏中输入cmd打开命令行 在本地找到adb.exe路径(如图1.1),把adb.exe拖到cmd命令行敲击回车显示所有可操作帮助示例(如图1.2). 图1.1 adb.exe路径 图1.2 adb命令示例 如果不输入adb的正确路径就不能进行正常显示,如图1.3: 图1.3adb未能正确打开 为了保证adb在任何路径下都能使用,

    赵雅智_android系统联系人app分析并获取数据

    手机联系人存放位置 和短信一样在data-data下 手机联系人数据库解析 将contacts2.db表导出,通过SQLiteexpert查看 mimetypes表:存放的数据类型(电话,头像,姓名,邮箱) 外键: raw_contacts表:存放联系人的id contact_id:联系人id display_name:联系人姓名 data表:存放联系人的数据 data1:联系人数据 data2:在mimetypes表中data1表示值得意义 mimetype_id:联系人ID,data数据所属

    赵雅智_android样式与主题

    样式与主题的区别 样式应用于特殊的组件,主题应用与整个应用或整个Activity 主题不仅单单显示内容的风格(大小.颜色),而且可以设置窗口的显示风格 当主题的设置属性与样式的设置属相相同时,系统按样式的设置属性显示 系统定义的一些常有主题: <activity android:theme="@android:style/Theme.Dialog"></activity>对话框风格 <activity android:theme="@androi

    赵雅智_android多线程下载带进度条

    progressBar说明 在某些操作的进度中的可视指示器,为用户呈现操作的进度,还它有一个次要的进度条,用来显示中间进度,如在流媒体播放的缓冲区的进度.一个进度条也可不确定其进度.在不确定模式下,进度条显示循环动画.这种模式常用于应用程序使用任务的长度是未知的. XML重要属性 android:progressBarStyle:默认进度条样式 android:progressBarStyleHorizontal:水平样式 progressBar重要方法 getMax():返回这个进度条的范围的

    赵雅智_Android Paint

    要绘图,首先得调整画笔,待画笔调整好之后,再将图像绘制到画布上,这样才可以显示在手机屏幕上.Android 中的画笔是 Paint类,Paint 中包含了很多方法对其属性进行设置,主要方法如下: setAntiAlias: 设置画笔的锯齿效果. setColor: 设置画笔颜色 setARGB:  设置画笔的a,r,p,g值. setAlpha:  设置Alpha值 setTextSize: 设置字体尺寸. setStyle:  设置画笔风格,空心或者实心. setStrokeWidth: 设置

    赵雅智_android测试

    测试概念 从是否关心软件内部结构和具体实现的角度划分 黑盒测试:只关心程序执行的过程和结果 白盒测试:根据源代码写测试方法或者测试用例 灰盒测试:是介于白盒测试与黑盒测试之间的 从软件开发的过程按阶段划分有 A.单元测试 B.集成测试 C.确认测试 D.系统测试 E.验收测试 F.回归测试 G.Alpha测试 新建测试项目测试 新建测试项目 新建测试类 在本类创建测试类 新建测试类继承AndroidTestCase类 配置测试设备和类库 配置测试设备 配置类库 AndroidManifest.x