zoukankan      html  css  js  c++  java
  • 使用ListView时遇到的问题

    这周练习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()方法重新绘制。


  • 相关阅读:
    [BZOJ]2589: Spoj 10707 Count on a tree II
    [BZOJ]2434: [Noi2011]阿狸的打字机
    Codeforces Round #408 (Div. 2)
    [BZOJ]2653: middle
    洛谷4月月赛R1
    2017省夏令营Day8
    2017省夏令营Day7
    2017省夏令营Day6
    【20170604校内模拟赛】香蕉
    【20170602模拟赛】秋之国的夏日祭
  • 原文地址:https://www.cnblogs.com/krislight1105/p/3748375.html
Copyright © 2011-2022 走看看