这周练习ListView时遇到了一个问题,从数据库中查询出的数据绑定到LIstView上,长按某个item进行删除操作,每次点击item取得的id都不对,调了半天终于找到了原因,关键是自己对自定义的BaseAdapter没有理解深刻。

先说说ListView使用BaseAdapter的优化技巧。

一般当系统提供的Adapter无法满足项目需求时,就需要自己定制一个Adpater,实现getView等方法给每一个item一个样式,getView方法就好比每一个Item对象绘制到屏幕上时会对我发一个消息:"嘿,boy,我要出现在你面前了,但是我还不知道你希望我长啥样,请帮忙在getView方法帮我选一个样式!"。于是我们就帮item绘制一个新的样式布局。但是每次item这家伙要我们帮忙的时候,都重新绘制布局对象,显然会对系统性能产生影响,所以我们需要优化一下,把布局缓存起来,这里官方推荐的是采用ViewHolder对象,说白了就是一个单例模式,判断为空时则新建一个,并存到某个缓存中,不为空,则直接从缓存取出来,丢给item.

具体代码如下:

public class NoteListAdapter extends BaseAdapter {
private List<Note> noteList = null;
private LayoutInflater layoutInflater;
private static final String TAG = NoteListAdapter.class.getSimpleName(); public NoteListAdapter(Context context, List<Note> list) {
this.noteList = list;
layoutInflater = LayoutInflater.from(context);
} public void setNoteList(List<Note> noteList) {
this.noteList = noteList;
} // 返回顯示的List中Item的個數
@Override
public int getCount() {
return noteList.size();
} //得到指定位置的Item對象
@Override
public Object getItem(int position) {
return noteList.get(position);
} //得到Item的Id
@Override
public long getItemId(int position) {
return position;
} @SuppressLint("SimpleDateFormat")
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Log.i(TAG, "getView被調用");
ViewHolder holder;
if (convertView == null) {
convertView = layoutInflater.inflate(
R.layout.note_list, null);
holder = new ViewHolder();
TextView tv = (TextView) convertView
.findViewById(R.id.tv_info_title);
holder.setInfotitle(tv);
TextView tvtime = (TextView) convertView
.findViewById(R.id.tv_info_time);
holder.setInfotime(tvtime);
convertView.setTag(holder);
}else {
holder = (ViewHolder) convertView.getTag();
}
if(!TextUtils.isEmpty(noteList.get(position).getTitle().toString().trim())){
long id = noteList.get(position).getId();
String title = noteList.get(position).getTitle();
Date date = noteList.get(position).getCreateDate();
Log.i(TAG, "從Adapter查出來的Id"+id);
holder.getInfotitle().setText(title);
SimpleDateFormat format = new SimpleDateFormat("yyyy/MM/dd");
holder.getInfotime().setText(format.format(date));
}
return convertView;
} private class ViewHolder {
private TextView infotitle;
private TextView infotime; public TextView getInfotitle() {
return infotitle;
} public void setInfotitle(TextView infotitle) {
this.infotitle = infotitle;
} public TextView getInfotime() {
return infotime;
} public void setInfotime(TextView infotime) {
this.infotime = infotime;
} } }

在这里有个地方开始没有注意

 long id = noteList.get(position).getId();

这一句代码id是根据postition的位置来得到的。

于是在我点击item时取得的id应该是通过参数中position变量获取而不是参数中的id变量

先给出开始时的错误代码:

	//点击
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
Intent intent = new Intent(this,NoteAddActivity.class);
//这个地方取到的id不正确
		intent.putExtra("id", id);
intent.putExtra("edit", true);
startActivity(intent);
}

正确的代码如下:

	//点击
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
Intent intent = new Intent(this,NoteAddActivity.class);
id = noteList.get(position).getId();
intent.putExtra("id", id);
intent.putExtra("edit", true);
startActivity(intent);
}

另外当在上下文菜单获取item的id时只有一个MenuItem对象参数,这时候应该借助AdapterView.AdapterContextMenuInfo对象获取id

代码片段如下:

@Override
public boolean onContextItemSelected(MenuItem item) {
//獲得上下文菜單信息
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)item.getMenuInfo();
//點擊的Item的ID
final Long MID = noteList.get(info.position).getId();
switch (item.getItemId()) {
//刪除
case ITEM1:
service = DbService.getInstance(this);
AlertDialog.Builder builder = new AlertDialog.Builder(ManagerActivity.this);
builder.setTitle("提示").setIcon(android.R.drawable.ic_dialog_alert).setMessage("確定刪除嗎?")
.setNegativeButton("否", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
}).setPositiveButton("是", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Runnable deleteNote = new Runnable() {
@Override
public void run() {
//發送消息給handler
service.deleteNote(MID);
Toast.makeText(ManagerActivity.this, "刪除成功", Toast.LENGTH_SHORT)
.show();
Log.i(TAG, "刪除的ID"+MID);
noteList = service.loadAllNote();
ma.setNoteList(noteList);
ma.notifyDataSetChanged();
}
};
myHandler.post(deleteNote);
}
}).create().show();
return true;

最后注意的地方是adpter中的list数据如果有变化,需要把新的list对象set给adpter对象,后面别忘了加上notifyDataSetChanged()方法重新绘制。

使用ListView时遇到的问题的更多相关文章

  1. 滚动ListView时图像顺序混乱

    本文选自StackOverflow(简称:SOF)精选问答汇总系列文章之一,本系列文章将为读者分享国外最优质的精彩问与答,供读者学习和了解国外最新技术.本文将为读者讲解滚动ListView时图像顺序混 ...

  2. 深入理解使用ListView时ArrayAdapter、SimpleAdapter、BaseAdapter的原理

    在使用ListView的时候,我们传给setAdapter方法的Adapter通常是ArrayAdapter.SimpleAdapter.BaseAdapter,但是这几个Adapter内部究竟是什么 ...

  3. ScrollView中嵌套ListView时,listview高度显示的问题

    方法一:直接更改listview的控件高度,动态获取(根据条目和每个条目的高度获取) 前几天因为项目的需要,要在一个ListView中放入另一个ListView,也即在一个ListView的每个Lis ...

  4. 使用ListView 时,遇到了 Your content must have a ListView whose id attribute is 'android.R.id.list' 错误

    今天在开发Android小应用的时候,使用到了ListView,在使用自己创建的listview风格的时候,就出现了如标题的错误提示信息,这个就让我纳闷了,以前也不会出现这个问题啊,而且也可以运行,赶 ...

  5. ScrollView嵌套listview 时根据内容动态设置listview高度

    public static void setListViewHeightBasedOnChilds(ListView listView){ ListAdapter listAdapter = list ...

  6. ListView嵌套ListView时发生:View too large to fit into drawing cache的问题

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXkxMzg3/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/d ...

  7. NestedScrollView嵌套ListView时只显示一行的解决方法

    在使用CoordinatorLayout和AppBarLayout实现嵌套滑动的时候,出现listview没有嵌套滑动: 如果要实现嵌套滑动,则需要添加NestedScrollView,但是结果发现l ...

  8. 【Android - 问题解决】之ScrollView嵌套ListView时总是自动滑动到ListView顶部的问题

    最近做了一个项目,里面有一个ScrollView嵌套ListView的布局. 做出来之后发现,进入这个界面之后,总是自动滑动到ListView的顶部,而ScrollView中位于ListView上面的 ...

  9. wpf 遍历listview 时 传入指定类型 得到指定类型控件info

    private ChildType FindVisualChild<ChildType>(DependencyObject obj) where ChildType : Dependenc ...

随机推荐

  1. C# winCE连接SQL数据库

    General network error.  Check your network documentation. 错误解决方法 1. public static string Sqlstr = &q ...

  2. css实现基础几何图形

    我们知道,css3通过border-radius.animation.transform等“新”特性可以绘制很多精致的图形.比如腾讯企鹅Logo.超能陆战队中的大白机器人.太阳系.小黄人.叮当猫.安卓 ...

  3. jqery选择器

    根据可见性 属性 匹配元素 <!doctype html> <html lang="en"> <head> <meta charset=& ...

  4. 实现方法 C# button快捷键

    本文讲解了三种方法实现C# button快捷键,如Alt + *(按钮快捷键),Ctrl+*及其他组合键等. C# button快捷键之第一种:Alt + *(按钮快捷键) 在大家给button.la ...

  5. asp.net 开发问题:Web 服务器上的请求筛选被配置为拒绝该请求,因为内容长度超过配置的值。

    "Web 服务器上的请求筛选被配置为拒绝该请求,因为内容长度超过配置的值." 这个问题在开发需要上传文件的时候可能会遇到,今天遇到这个问题,百度过也有挺多的修改方法. 方法1: 修 ...

  6. 那天有个小孩跟我说LINQ(二)转载

    1  LINQ TO Objects续(代码下载)      新建项目 linq_Ch2控制台程序,新建一个Entity文件夹    1.1 学生成绩查询(练习Join)         有三张表如下 ...

  7. dumpbin工具的使用

    当我们需要查看一个dll或exe文件中的包含的函数或是依赖的函数之类的信息,可以使用Visual Studio自带的工具dumpbin来实现,使用方法为: 1/ 启动Visual Studio 命令行 ...

  8. CWnd::UpdateData

    CWnd::UpdateData 格式: BOOL UpdateData( BOOL bSaveAndValidate = TRUE ); 描述:调用该成员函数初始化在对话框中的数据,或检索和验证对话 ...

  9. 16_AOP入门准备_动态代理模式

    [工程截图] [PersonDao.java] package com.HigginCui.daoProxy; //目标类接口 public interface PersonDao { public ...

  10. c++ 中的8种智能指针[转]

    一.简介 由于 C++ 语言没有自动内存回收机制,程序员每次 new 出来的内存都要手动 delete.程序员忘记 delete,流程太复杂,最终导致没有 delete,异常导致程序过早退出,没有执行 ...