转自:http://blog.csdn.net/deng0zhaotai/article/details/22486423
LoaderManager.LoaderCallbacks是3.0之后出现的新特性,通过LoaderManager.LoaderCallbacks接口可以很轻松的实现异步加载数据到Fragment或Activity 中,Loaders提供了回调机制onLoadFinished()通知最终的运行结果,有点类似AsyncTask类,但由于Loader对于并发可以用过Loader管理器统一管理,所以更适合批量处理多个异步任务的处理(当然内部仍然是多线程)。要使用Loader就要实现LoaderManager.LoaderCallbacks接口,并实现它的抽象方法
下面是我加载通话记录的Demo,实现了过滤拨入、拨出、未接、所有,删除单条记录,拨号功能,实现效果图
目录结构
ListView中每个item的布局listview_item.xml
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent" >
- <ImageView
- android:id="@+id/bt_icon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerVertical="true"
- android:layout_marginLeft="10dp"
- android:background="#00000000"
- android:contentDescription="@string/content_description"
- android:src="@drawable/calllog_incoming" />
- <TextView
- android:id="@+id/tv_name"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="10dp"
- android:layout_marginTop="2dp"
- android:layout_toRightOf="@id/bt_icon"
- android:textSize="23sp" />
- <TextView
- android:id="@+id/tv_number"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignLeft="@id/tv_name"
- android:layout_below="@id/tv_name"
- android:layout_marginBottom="2dp"
- android:textColor="#7f7f7f"
- android:textSize="16sp" />
- <TextView
- android:id="@+id/tv_date"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignTop="@id/tv_number"
- android:layout_marginLeft="10dp"
- android:layout_toRightOf="@id/tv_number"
- android:ellipsize="end"
- android:textColor="#7f7f7f"
- android:textSize="16sp" />
- <ImageButton
- android:id="@+id/btn_delete"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:layout_centerVertical="true"
- android:layout_marginRight="10dp"
- android:background="#00000000"
- android:contentDescription="@string/content_description"
- android:focusableInTouchMode="false"
- android:src="@drawable/cl_delete_selector" />
- <ImageButton
- android:id="@+id/btn_call"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerVertical="true"
- android:layout_marginRight="5dp"
- android:layout_toLeftOf="@id/btn_delete"
- android:background="#00000000"
- android:contentDescription="@string/content_description"
- android:focusableInTouchMode="false"
- android:src="@drawable/cl_call_selector" />
- </RelativeLayout>
整个Activity的布局文件
- <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"
- tools:context=".MainActivity" >
- <TextView
- android:id="@+id/tv_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/hello_world" />
- <Button
- android:id="@+id/btn_all"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/tv_text"
- android:text="@string/all" />
- <Button
- android:id="@+id/btn_incoming"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/tv_text"
- android:layout_marginLeft="20dp"
- android:layout_toRightOf="@id/btn_all"
- android:text="@string/incoming" />
- <Button
- android:id="@+id/btn_outcoming"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/btn_all"
- android:layout_marginTop="10dp"
- android:text="@string/outcoming" />
- <Button
- android:id="@+id/btn_missed"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignLeft="@id/btn_incoming"
- android:layout_below="@id/btn_all"
- android:layout_marginTop="10dp"
- android:layout_toRightOf="@id/btn_outcoming"
- android:text="@string/missed" />
- <View
- android:id="@+id/line_layout"
- android:layout_width="match_parent"
- android:layout_height="2dp"
- android:layout_below="@id/btn_missed"
- android:background="#000000" >
- </View>
- <ListView
- android:id="@+id/lv_list"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_below="@id/line_layout"
- android:clipToPadding="false"
- android:divider="#ff553311"
- android:dividerHeight="2dp"
- android:fadingEdge="none"
- android:paddingTop="10dp" />
- </RelativeLayout>
ListView对应的适配器MyCursorAdapter.java
- package com.dzt.loaderdemo;
- import java.text.SimpleDateFormat;
- import java.util.Date;
- import java.util.Locale;
- import android.content.Context;
- import android.content.Intent;
- import android.database.Cursor;
- import android.net.Uri;
- import android.provider.CallLog;
- import android.util.Log;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import android.view.View.OnClickListener;
- import android.widget.CursorAdapter;
- import android.widget.ImageButton;
- import android.widget.ImageView;
- import android.widget.TextView;
- class MyCursorAdapter extends CursorAdapter {
- private static final String TAG = "dzt";
- private final Context mContext;
- public MyCursorAdapter(Context context, Cursor c) {
- this(context, c, true);
- // TODO Auto-generated constructor stub
- }
- public MyCursorAdapter(Context context, Cursor c, boolean autoRequery) {
- super(context, c, autoRequery);
- // TODO Auto-generated constructor stub
- mContext = context;
- }
- public MyCursorAdapter(Context context, Cursor c, int flags) {
- super(context, c, flags);
- // TODO Auto-generated constructor stub
- mContext = context;
- }
- @Override
- public View newView(Context context, Cursor cursor, ViewGroup parent) {
- // TODO Auto-generated method stub
- LayoutInflater inflater = LayoutInflater.from(context);
- return inflater.inflate(R.layout.listview_item, parent, false);
- }
- @Override
- public void bindView(View view, Context context, Cursor cursor) {
- // TODO Auto-generated method stub
- if (cursor == null)
- return;
- final String id = cursor.getString(0);
- String number = cursor.getString(1);
- String name = cursor.getString(2);
- int type = cursor.getInt(3);
- String date = cursor.getString(4);
- ImageView TypeView = (ImageView) view.findViewById(R.id.bt_icon);
- TextView nameCtrl = (TextView) view.findViewById(R.id.tv_name);
- if (name == null) {
- nameCtrl.setText(mContext.getString(R.string.name_unknown));
- } else {
- nameCtrl.setText(name);
- }
- TextView numberCtrl = (TextView) view.findViewById(R.id.tv_number);
- numberCtrl.setText(number);
- String value = ComputeDate(date);
- TextView dateCtrl = (TextView) view.findViewById(R.id.tv_date);
- dateCtrl.setText(value);
- switch (type) {
- case CallLog.Calls.INCOMING_TYPE:
- TypeView.setImageResource(R.drawable.calllog_incoming);
- break;
- case CallLog.Calls.OUTGOING_TYPE:
- TypeView.setImageResource(R.drawable.calllog_outcoming);
- break;
- case CallLog.Calls.MISSED_TYPE:
- TypeView.setImageResource(R.drawable.calllog_missed);
- break;
- case 4: // CallLog.Calls.VOICEMAIL_TYPE
- break;
- default:
- break;
- }
- ImageButton dailBtn = (ImageButton) view.findViewById(R.id.btn_call);
- dailBtn.setTag(number);
- dailBtn.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- // TODO Auto-generated method stub
- // Intent.ACTION_CALL_PRIVILEGED 由于Intent中隐藏了,只能用字符串代替
- Intent intent = new Intent(Intent.ACTION_CALL, Uri.fromParts(
- "tel", (String) v.getTag(), null));
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mContext.startActivity(intent);
- }
- });
- ImageButton deleteBtn = (ImageButton) view
- .findViewById(R.id.btn_delete);
- deleteBtn.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- // TODO Auto-generated method stub
- // 根据ID进行记录删除
- String where = CallLog.Calls._ID + "=?";
- String[] selectionArgs = new String[] { id };
- int result = mContext.getContentResolver().delete(
- CallLog.Calls.CONTENT_URI, where, selectionArgs);
- Log.d(TAG, "11result = " + result);
- }
- });
- }
- private String ComputeDate(String date) {
- long callTime = Long.parseLong(date);
- long newTime = new Date().getTime();
- long duration = (newTime - callTime) / (1000 * 60);
- String value;
- // SimpleDateFormat sfd = new
- // SimpleDateFormat("yyyy-MM-dd HH:mm:ss",
- // Locale.getDefault());
- // String time = sfd.format(callTime);
- // Log.d(TAG, "[MyCursorAdapter--ComputeDate] time = " + time);
- // 进行判断拨打电话的距离现在的时间,然后进行显示说明
- if (duration < 60) {
- value = duration + "分钟前";
- } else if (duration >= 60 && duration < MainActivity.DAY) {
- SimpleDateFormat sdf = new SimpleDateFormat("HH:mm",
- Locale.getDefault());
- value = sdf.format(new Date(callTime));
- // value = (duration / 60) + "小时前";
- } else if (duration >= MainActivity.DAY
- && duration < MainActivity.DAY * 2) {
- value = "昨天";
- } else if (duration >= MainActivity.DAY * 2
- && duration < MainActivity.DAY * 3) {
- value = "前天";
- } else if (duration >= MainActivity.DAY * 7) {
- SimpleDateFormat sdf = new SimpleDateFormat("MM/dd",
- Locale.getDefault());
- value = sdf.format(new Date(callTime));
- } else {
- value = (duration / MainActivity.DAY) + "天前";
- }
- return value;
- }
- }
加载器是放在MainActivity.java类当中
- package com.dzt.loaderdemo;
- import android.app.Activity;
- import android.app.LoaderManager;
- import android.content.CursorLoader;
- import android.content.Loader;
- import android.database.Cursor;
- import android.os.Bundle;
- import android.provider.CallLog;
- import android.util.Log;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- import android.widget.ListView;
- /**
- * 使用加载器加载通话记录
- *
- * @author Administrator
- *
- */
- public class MainActivity extends Activity {
- private static final String TAG = "dzt";
- // 查询指定的条目
- private static final String[] CALLLOG_PROJECTION = new String[] {
- CallLog.Calls._ID, CallLog.Calls.NUMBER, CallLog.Calls.CACHED_NAME,
- CallLog.Calls.TYPE, CallLog.Calls.DATE };
- static final int DAY = 1440; // 一天的分钟值
- private static final int ALL = 0; // 默认显示所有
- private static final int INCOMING = CallLog.Calls.INCOMING_TYPE; // 来电
- private static final int OUTCOMING = CallLog.Calls.OUTGOING_TYPE; // 拔号
- private static final int MISSED = CallLog.Calls.MISSED_TYPE; // 未接
- private ListView mListView;
- private MyLoaderListener mLoader = new MyLoaderListener();
- private MyCursorAdapter mAdapter;
- private int mCallLogShowType = ALL;
- private boolean m_FinishLoaderFlag = false; // 第一次加载完成
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- initWidgets();
- initMyLoader();
- }
- private void initWidgets() {
- mListView = (ListView) findViewById(R.id.lv_list);
- Button btn = (Button) findViewById(R.id.btn_all);
- btn.setOnClickListener(new buttonListener());
- btn = (Button) findViewById(R.id.btn_incoming);
- btn.setOnClickListener(new buttonListener());
- btn = (Button) findViewById(R.id.btn_outcoming);
- btn.setOnClickListener(new buttonListener());
- btn = (Button) findViewById(R.id.btn_missed);
- btn.setOnClickListener(new buttonListener());
- mAdapter = new MyCursorAdapter(MainActivity.this, null);
- mListView.setAdapter(mAdapter);
- }
- private void initMyLoader() {
- getLoaderManager().initLoader(0, null, mLoader);
- }
- /**
- * 实现一个加载器
- *
- * @author Administrator
- *
- */
- private class MyLoaderListener implements
- LoaderManager.LoaderCallbacks<Cursor> {
- @Override
- public Loader<Cursor> onCreateLoader(int id, Bundle args) {
- // TODO Auto-generated method stub
- m_FinishLoaderFlag = false;
- CursorLoader cursor = new CursorLoader(MainActivity.this,
- CallLog.Calls.CONTENT_URI, CALLLOG_PROJECTION, null, null,
- CallLog.Calls.DEFAULT_SORT_ORDER);
- Log.d(TAG, "MyLoaderListener---------->onCreateLoader");
- return cursor;
- }
- @Override
- public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
- // TODO Auto-generated method stub
- if (data == null)
- return;
- Cursor tempData = data;
- if (tempData.getCount() == 0) {
- Log.d(TAG,
- "MyLoaderListener---------->onLoadFinished count = 0");
- mAdapter.swapCursor(null);
- return;
- }
- if (m_FinishLoaderFlag) {
- tempData = null;
- String selection = null;
- String[] selectionArgs = null;
- if (mCallLogShowType == INCOMING) {
- selection = CallLog.Calls.TYPE + "=?";
- selectionArgs = new String[] { "1" };
- } else if (mCallLogShowType == OUTCOMING) {
- selection = CallLog.Calls.TYPE + "=?";
- selectionArgs = new String[] { "2" };
- } else if (mCallLogShowType == MISSED) {
- selection = CallLog.Calls.TYPE + "=?";
- selectionArgs = new String[] { "3" };
- }
- tempData = getContentResolver().query(
- CallLog.Calls.CONTENT_URI, CALLLOG_PROJECTION,
- selection, selectionArgs,
- CallLog.Calls.DEFAULT_SORT_ORDER);
- }
- mAdapter.swapCursor(tempData);
- Log.d(TAG,
- "MyLoaderListener---------->onLoadFinished data count = "
- + data.getCount());
- m_FinishLoaderFlag = true;
- }
- @Override
- public void onLoaderReset(Loader<Cursor> loader) {
- // TODO Auto-generated method stub
- Log.d(TAG, "MyLoaderListener---------->onLoaderReset");
- mAdapter.swapCursor(null);
- }
- }
- private class buttonListener implements OnClickListener {
- @Override
- public void onClick(View v) {
- // TODO Auto-generated method stub
- switch (v.getId()) {
- case R.id.btn_all:
- allCalllog();
- break;
- case R.id.btn_incoming:
- incomingCalllog();
- break;
- case R.id.btn_outcoming:
- outcomingCalllog();
- break;
- case R.id.btn_missed:
- missedCalllog();
- break;
- default:
- break;
- }
- }
- }
- private void allCalllog() {
- mCallLogShowType = ALL;
- String selection = null;
- String[] selectionArgs = null;
- Cursor allCursor = getContentResolver().query(
- CallLog.Calls.CONTENT_URI, CALLLOG_PROJECTION, selection,
- selectionArgs, CallLog.Calls.DEFAULT_SORT_ORDER);
- mAdapter.swapCursor(allCursor);
- }
- private void incomingCalllog() {
- mCallLogShowType = INCOMING;
- String selection = CallLog.Calls.TYPE + "=?";
- String[] selectionArgs = new String[] { "1" };
- Cursor incomingCursor = getContentResolver().query(
- CallLog.Calls.CONTENT_URI, CALLLOG_PROJECTION, selection,
- selectionArgs, CallLog.Calls.DEFAULT_SORT_ORDER);
- mAdapter.swapCursor(incomingCursor);
- }
- private void outcomingCalllog() {
- mCallLogShowType = OUTCOMING;
- String selection = CallLog.Calls.TYPE + "=?";
- String[] selectionArgs = new String[] { "2" };
- Cursor outcomingCursor = getContentResolver().query(
- CallLog.Calls.CONTENT_URI, CALLLOG_PROJECTION, selection,
- selectionArgs, CallLog.Calls.DEFAULT_SORT_ORDER);
- mAdapter.swapCursor(outcomingCursor);
- }
- private void missedCalllog() {
- mCallLogShowType = MISSED;
- String selection = CallLog.Calls.TYPE + "=?";
- String[] selectionArgs = new String[] { "3" };
- Cursor missedCursor = getContentResolver().query(
- CallLog.Calls.CONTENT_URI, CALLLOG_PROJECTION, selection,
- selectionArgs, CallLog.Calls.DEFAULT_SORT_ORDER);
- mAdapter.swapCursor(missedCursor);
- }
- }
完整的Demo
http://download.csdn.net/detail/deng0zhaotai/7116173