Android ListView示例在结果视图中复制联系人
我正在尝试中找到的Android ListView示例在结果视图中复制联系人,android,listview,android-contacts,Android,Listview,Android Contacts,我正在尝试中找到的ListView示例。或多或少,我已经将示例中的代码复制到了活动中(我现在只省略了progressbar) 一切正常,除了列表视图显示我设备上的每个联系人的副本(运行Nexus7,Android 4.2) 每个联系人在列表视图中重复6-7次。我使用的游标已经返回了太多的结果(它应该只返回3个项目,因为我在Nexus atm上只有三个联系人。)。当我检查RAW\u CONTACT\u ID时,重复项总是指向相同的ID值(即,我只得到3个唯一的ID) 这意味着不是我的视图代码有问题
ListView
示例。或多或少,我已经将示例中的代码复制到了活动中(我现在只省略了progressbar
)
一切正常,除了列表视图
显示我设备上的每个联系人的副本(运行Nexus7,Android 4.2)
每个联系人在列表视图中重复6-7次。我使用的游标已经返回了太多的结果(它应该只返回3个项目,因为我在Nexus atm上只有三个联系人。)。当我检查RAW\u CONTACT\u ID
时,重复项总是指向相同的ID值(即,我只得到3个唯一的ID)
这意味着不是我的视图代码有问题
所以问题是适配器中会出现什么问题
为什么光标返回所有联系人的副本?或者设备上是否存在导致返回这些副本的原因
我看了其他的问题,但似乎没有一个是关于这个问题的
public class ThemeSelectorActivity extends ListActivity
implements LoaderManager.LoaderCallbacks{
private static final String TAG = "ThemeSelector";
// The rows that we will retrieve from the db (Contacts used as dummy data)
static final String[] PROJECTION = new String[] {ContactsContract.Data._ID,
ContactsContract.Data.DISPLAY_NAME};
// The select criteria for fetching contacts
static final String SELECTION = "((" +
ContactsContract.Data.DISPLAY_NAME + " NOTNULL) AND (" +
ContactsContract.Data.DISPLAY_NAME + " != '' ))";
// The Adapter being used to display the list's data
SimpleCursorAdapter mAdapter;
@Override
public void onCreate(Bundle savedInstanceState)
{
Log.d(TAG, "Create...");
super.onCreate(savedInstanceState);
// set the listview to be selectable
getListView().setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
// For the cursor adapter, specify which columns go into which views
String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME};
int[] toViews = {android.R.id.text1}; // The TextView in simple_list_item_1
// Create an empty adapter we will use to display the loaded data.
// We pass null for the cursor, then update it in onLoadFinished()
mAdapter = new SimpleCursorAdapter(this,
android.R.layout.simple_list_item_1, null,
fromColumns, toViews, 0);
setListAdapter( mAdapter );
// Prepare the loader. Either re-connect with an existing one,
// or start a new one.
getLoaderManager().initLoader(0, null, this);
}
// Called when a new Loader needs to be created
public Loader onCreateLoader(int id, Bundle args) {
// Now create and return a CursorLoader that will take care of
// creating a Cursor for the data being displayed.
return new CursorLoader(this, ContactsContract.Data.CONTENT_URI,
PROJECTION, SELECTION, null, null);
}
// Called when a previously created loader has finished loading
public void onLoadFinished(Loader loader, Cursor data) {
// Swap the new cursor in. (The framework will take care of closing the
// old cursor once we return.)
mAdapter.swapCursor(data);
}
// Called when a previously created loader is reset, making the data unavailable
public void onLoaderReset(Loader loader) {
// This is called when the last Cursor provided to onLoadFinished()
// above is about to be closed. We need to make sure we are no
// longer using it.
mAdapter.swapCursor(null);
}
@Override
/**
* Start activity that shows a preview of the selected theme
*/
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
//String item = (String) getListAdapter().getItem(position);
//Toast.makeText(this, item + " selected", Toast.LENGTH_LONG).show();
}
}
公共类ThemeSelectorActivity扩展了ListActivity
实现LoaderManager.LoaderCallbacks{
私有静态最终字符串TAG=“ThemeSelector”;
//我们将从数据库中检索的行(联系人用作虚拟数据)
静态最终字符串[]投影=新字符串[]{contacts contract.Data.\u ID,
contacts contract.Data.DISPLAY\u NAME};
//获取联系人的选择条件
静态最终字符串选择=“(”+
contacts contract.Data.DISPLAY_NAME+“NOTNULL)和(”+
contacts contract.Data.DISPLAY_NAME+“!=”);
//用于显示列表数据的适配器
简单的适应;
@凌驾
创建时的公共void(Bundle savedInstanceState)
{
Log.d(标记“创建…”);
super.onCreate(savedInstanceState);
//将listview设置为可选择
getListView().setChoiceMode(AbsListView.CHOICE\u MODE\u SINGLE);
//对于光标适配器,指定哪些列进入哪些视图
String[]fromColumns={ContactsContract.Data.DISPLAY\u NAME};
int[]toViews={android.R.id.text1};//简单列表项目中的TextView
//创建一个空适配器,用于显示加载的数据。
//我们为游标传递null,然后在onLoadFinished()中更新它
mAdapter=新的SimpleCursorAdapter(此,
android.R.layout.simple_list_item_1,null,
从列到视图,0);
setListAdapter(mAdapter);
//准备加载程序。或者重新连接现有加载程序,
//或者开始一个新的。
getLoaderManager().initLoader(0,null,this);
}
//需要创建新加载程序时调用
公共加载器onCreateLoader(int-id,Bundle-args){
//现在创建并返回一个游标加载程序,它将处理
//为正在显示的数据创建光标。
返回新的游标装入器(此,contacts contract.Data.CONTENT\u URI,
投影,选择,空,空);
}
//当先前创建的加载程序完成加载时调用
public void onLoadFinished(加载器、光标数据){
//在中交换新光标。(框架将负责关闭
//我们返回后,将返回旧光标。)
mAdapter.swapCursor(数据);
}
//重置以前创建的加载程序时调用,使数据不可用
公共void onLoaderReset(加载器){
//当提供给onLoadFinished()的最后一个游标时调用
//以上内容即将关闭。我们需要确保我们没有
//不再使用它。
mAdapter.swapCursor(空);
}
@凌驾
/**
*启动显示所选主题预览的活动
*/
public void onListItemClick(列表视图l、视图v、整数位置、长id){
super.onListItemClick(左、右、位置、id);
//字符串项=(字符串)getListAdapter().getItem(位置);
//Toast.makeText(此项+选定项),Toast.LENGTH_LONG.show();
}
}
Contacts contract.Data.CONTENT\u URI显示联系人的所有数据
您应该使用ContactsContract.Contacts.CONTENT\u URI正如我所说,它基本上是我链接到()的示例的副本,只是暂时删除了进度指示器。但是更新了完整性问题,因为示例有效。你的代码基本上不是。为了确保我在测试中没有遗漏一些琐碎的东西,我在Eclipse中创建了一个新的Android项目(API级别15,min SDK版本14),只是逐步完成了新项目向导。然后复制粘贴示例中的所有代码,将类的名称从ListViewLoader更改为MainActivity(以匹配开始活动),将读取权限添加到清单中,然后运行示例。结果与之前相同,即显示联系人列表,但每个联系人都重复了几次。有什么想法吗?除非您需要跨多个子部分获取数据,否则这是可行的,在这种情况下,数据表实际上更易于处理,因为您可以在一个查询中完成。我同意您@BrillPappin的观点,如果您想获取电子邮件,您不能使用Contacts contract.Contacts.CONTENT\u URI。但是,嘿@BrillPappin,是否可以跨多个子部分而不是使用数据表获取数据?因为您说过处理数据表更容易。谢谢我认为您将需要多个查询,尽管每个android版本的API似乎都有一些变化。