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><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>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;
}
}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);
}
}
加载器的使用就是重写三个回调函数,并在加载完时设置Adapter的Cursor,使用Loader之后,只要数据源发生变化,就会自动调用onLoadFinished(),此时listview也会自动刷新
完整的Demo
http://download.csdn.net/detail/deng0zhaotai/7116173
Android加载器LoaderManager.LoaderCallbacks的使用,布布扣,bubuko.com
Android加载器LoaderManager.LoaderCallbacks的使用
原文:http://blog.csdn.net/deng0zhaotai/article/details/22486423