因为用于展示短信记录的是一个ListView,但是为了方便,可以直接继承自ListFragment,就可以免去写ListView对应的布局了,只需要写其item对应的布局即可。

item_sended_msg.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/sms_item"
android:padding="16dp"> <TextView
android:id="@+id/id_tv_sended_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp"/> <com.example.just.festival_sms.view.FlowLayout
android:id="@+id/id_fl_sended_contacts"
android:layout_width="match_parent"
android:layout_height="match_parent">
</com.example.just.festival_sms.view.FlowLayout> <LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:orientation="horizontal"> <TextView
android:id="@+id/id_tv_fes"
android:background="@drawable/tag_bg"
android:layout_marginRight="8dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" /> <TextView
android:id="@+id/id_tv_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout> </LinearLayout>

还有tag.xml,显示联系人的layout

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#0ffcdd"
android:background="@drawable/tag_bg"
android:layout_margin="4dp"> </TextView>

以及tag_bg.xml,用于显示联系人和节日的TextView的background 

<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <solid android:color="#ffffff"></solid>

    <stroke android:width="2dp" android:color="#0ffcdd"></stroke>

    <corners android:radius="8dp"></corners>

    <padding android:left="8dp" android:right="8dp" android:top="2dp" android:bottom="2dp"></padding>
</shape>

关于shape中的属性: 
http://www.oschina.net/question/166763_34833?fromerr=FBMFjTg7


SmsHistoryFragment.Java

需要注意,某些导入的包可能有多种选择,应该都是v4下的

public class SmsHistoryFragment extends ListFragment {
private static final int LOADER_ID =; private LayoutInflater mInflater;
private CursorAdapter mCursorAdapter; @Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState); mInflater=LayoutInflater.from(getActivity()); initLoader(); setupListAdapter(); } private void setupListAdapter() {
mCursorAdapter=new CursorAdapter(getActivity(),null,false) { //并不是每次都被调用的,它只在实例化view的时候调用,数据增加的时候也会调用
//但是在重绘(比如修改条目里的TextView的内容)的时候不会被调用
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
View view=mInflater.inflate(R.layout.item_sended_msg,parent,false);//注意是"包名.R"
return view;
} //在绘制Item之前一定会调用bindView方法,它在重绘的时候也同样被调用
@Override
public void bindView(View view, Context context, Cursor cursor) {
TextView tvContent= (TextView) view.findViewById(R.id.id_tv_sended_content);
FlowLayout flContacts= (FlowLayout) view.findViewById(R.id.id_fl_sended_contacts);
TextView tvFes= (TextView) view.findViewById(R.id.id_tv_fes);
TextView tvDate= (TextView) view.findViewById(R.id.id_tv_date); tvContent.setText(cursor.getString(cursor.getColumnIndex(SendedMsg.COLUMN_CONTENT)));
tvFes.setText(cursor.getString(cursor.getColumnIndex(SendedMsg.COLUMN_FESTIVAL_NAME))); //注意这里的date为long,int型会溢出
long date=cursor.getLong(cursor.getColumnIndex(SendedMsg.COLUMN_DATE));
tvDate.setText(parseDate(date)); String names=cursor.getString(cursor.getColumnIndex(SendedMsg.COLUMN_NAMES));
if(TextUtils.isEmpty(names)) {
return;
} //因为ListView的item有复用的可能性,所以每次都要先除去item中的flContacts在上一次使用时添加的view
flContacts.removeAllViews(); for (String name:names.split(",")) {
addTag(name, flContacts);
}
}
}; setListAdapter(mCursorAdapter);
} private String parseDate(long date) {
DateFormat df=new SimpleDateFormat("yyyy-MM-dd HH:mm");
return df.format(date);
} private void addTag(String name,FlowLayout fl) {
TextView tv= (TextView) mInflater.inflate(R.layout.tag,fl,false);
tv.setText(name);
fl.addView(tv);
} private void initLoader() {
getLoaderManager().initLoader(LOADER_ID,null,new LoaderManager.LoaderCallbacks<Cursor>() { //onCreateLoader是一个工厂方法,用来返回一个新的Loader
//LoaderManager将会在它第一次创建Loader的时候调用该方法
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
CursorLoader loader=new CursorLoader(getActivity(), SmsProvider.URI_SMS_ALL,null,null,null,null);
return loader;
} //onLoadFinished方法将在Loader创建完毕的时候自动调用
//在数据更新的时候也会调用
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
if(loader.getId()==LOADER_ID) {
mCursorAdapter.swapCursor(data);//更新mCursorAdapter的Cursor
}
} @Override
public void onLoaderReset(Loader<Cursor> loader) {
mCursorAdapter.swapCursor(null);
}
});
}
}

SmsHistoryFragment中,涉及到了LoaderManager与Loader,而关于这个知识点,推荐一篇优质博文,看完之后肯定会有所收获的。 
http://blog.csdn.net/murphykwu/article/details/35287303

还是回到本文中来,因为Android的设计之中,任何耗时的操作都不能放在UI主线程之中。所以类似于网络操作等等耗时的操作都需要使用异步的实现。而在ContentProvider之中,也有可能存在耗时的操作(当查询的数据量很大的时候),这个时候我们也需要使用异步的调用来完成数据的查。当使用异步的query的时候,我们就需要使用LoaderManager了。使用LoaderManager就可以在不阻塞UI主线程的情况下完成数据的加载。

还记得上一篇文章最后提及的两行代码吗?就是为了实时的更新数据用的,更进一步说,是为了同步ListView中显示数据(历史记录),两行代码缺一不可。(检测数据源是Loader的工作,Loader也会执行实际的同步载入操作,而在这之中,那两句代码就起到了一定的作用

另外,关于还有关于CursorAdapter,可以去看看这篇博文: 
http://www.bubuko.com/infodetail-734550.html

对了,小编在刚开始解读源码的时候有一个疑问,mCursorAdapter是在setupListAdapter中初始化的,但是initLoader中就用到了mCursorAdapter,为什么程序可以运行(因为这里是先initLoader再setupListAdapter)(但是实际中也可以先setupListAdapter再initLoader) 
后来实际测试了一下,发现部分具体的流程如下: 
onCreateLoader() -> 初始化mCursorAdapter ->setListAdapter(mCursorAdapter) 
-> onLoadFinished() 
这是因为getLoaderManager().initLoader()中传入的第三个参数是一个回调接口。

Android 节日短信送祝福(功能篇:2-短信历史记录Fragment的编写)的更多相关文章

  1. Android 节日短信送祝福(功能篇:1-数据库操作类与自定义ContentProvider)

    首先,还是展示一下部分目录结构:  在节日短信送祝福的功能实现方面,为了能够方便直观展示实现过程,小编我以Java文件为基础,一个一个来展示,免得到时候这个java文件写点,一下又跳到另外一个java ...

  2. Android 节日短信送祝福(UI篇:3-选择短信与发送短信的Activity的实现)

    一.ChooseMsgActivity的实现 1.布局文件 <RelativeLayout xmlns:android="http://schemas.android.com/apk/ ...

  3. Android service 服务的应用之电话监听器以及短信监听器

    首先建立一个项目工程文件,如下图所示:

  4. SpringBoot + Spring Security 学习笔记(五)实现短信验证码+登录功能

    在 Spring Security 中基于表单的认证模式,默认就是密码帐号登录认证,那么对于短信验证码+登录的方式,Spring Security 没有现成的接口可以使用,所以需要自己的封装一个类似的 ...

  5. Android手机使用广播监听手机收到的短信

    我们使用的Android手机在收到短信的时候会发出一条系统广播.该条广播中存放着接收到的短信的详细信息.本文将详细介绍如何通过动态注册广播来监听短信. 注册广播有两种方式,一种是动态注册,另一种是静态 ...

  6. GPRS的短信和打电话功能

    短信功能: 发短信设置文本格式就可以了:但收短信可能收到的是乱码,需要编写解码程序才可以: 关于打电话单片机复位功能: 首先要建立黑白名单制度过滤手机号,只运行白名单的手机对的单片机打电话:其它的不响 ...

  7. 客户注册功能,发短信功能分离 通过ActiveMQ实现

    客户注册功能,发短信功能分离 通过ActiveMQ 配置链接工厂, 配置session缓存工厂(引入链接工厂) 2.配置模板对象JmsTemplate 引入缓存工厂    指定消息模式(队列,发布和订 ...

  8. 项目一:在线下单(补充) activeMQ使用(重点) 重构客户注册功能,发短信功能分离

    1 课程计划 1.在线下单(补充) 2.activeMQ使用(重点) n 简介和安装 n activeMQ入门案例 n spring整合activeMQ应用 3.重构客户注册功能,发短信功能分离 n  ...

  9. 基于EasyDarwin EasyPusher实现Android手机直播推送功能

    EasyPusher直播推送在之前就已经稳定支持了Windows.Linux.ARM上的RTSP直播推送功能,配合EasyDarwin开源流媒体服务器,延时基本在1s以内,这个技术方案经过一年多时间, ...

随机推荐

  1. 怎样解决git提交代码冲突

    当我们使用git提交代码时,别人可能也同一时候改动了我们改动的文件,可是别人的先合入到配置库里边,这样当我们的提交要合入时.就会产生冲突,能够使用下面步骤来解决冲突: (1) git rebase   ...

  2. UVa 11094 - Continents

    题目:有一些岛屿在湖中.地图用两种字符表示.当前处在位置是一个岛屿.求除了当前岛屿外的最大岛屿. 分析:图论,floodfill.直接利用dfs求联通部分的面积就可以,然后取出最大. 说明:横线没有边 ...

  3. opera mini 改服

    opera mini 改服 下载 opera 和 opera mini ftp://ftp.opera.com/pub/opera/android/mini/ ftp://ftp.opera.com/ ...

  4. ViewPager+Fragmrnt最简单结合方法

    Fragment和ViewPager 本博文系本菜鸟第一次博文展示,有错误之处请虽然提出 FragmentPagerAdapter 谷歌官方提供了这么一个adapter(FragmentPagerAd ...

  5. string-format样式使用

    首先我们看如下代码 protected String calcu1() { StringBuffer resultB = new StringBuffer(); String str = null; ...

  6. Rdis-主从复制

    配置 配置一个从服务器非常简单, 只要在配置文件中增加以下的这一行就可以了: slaveof 192.168.1.1 6379 注:主:bind 192.168.10.1 (指定主机IP) 当然, 你 ...

  7. 怎么做好看的html5游戏界面

    怎么做好看的html5游戏界面 一.总结 一句话总结:html5应该是完全可以做特别好看的游戏界面的.最下面那个背景图完全是一张图片动的雪和小动物可以是gif,或者是canvas,右边的那各个选择框就 ...

  8. Codeforces Round #100 E. New Year Garland (第二类斯特林数+dp)

    题目链接: http://codeforces.com/problemset/problem/140/E 题意: 圣诞树上挂彩球,要求从上到下挂\(n\)层彩球.已知有\(m\)种颜色的球,球的数量不 ...

  9. FZU Problem 2062 Suneast & Yayamao

    http://acm.fzu.edu.cn/problem.php?pid=2062 题目大意: 给你一个数n,要求求出用多少个数字可以表示1~n的所有数. 思路: 分解为二进制. 对于一个数n,看它 ...

  10. Day1:If else流程判断

    一.if...else语句 if 条件成立: 执行条件成立后的代码 else: 执行条件不成立的代码 注:注意有冒号,python会强制缩进!一般语句都必须顶格写,缩进是缩进一个tab键,等于4个空格 ...