Android Adapter優化問題

      最近在使用BaseAdapter顯示錄製的視頻文件時,又是遇到了各種奇葩問題。比如:

        1>文件個數多時,快速上下滑動時,速度明顯緩慢,有點卡,更坑的是會出現異常退出;

        2>checkBox 點擊選擇時,其它頁面的相同位置的checkBox也會被選中;

        3>自定義的checkBox的圖標太小,如何增大checkBox的點擊區域;

        4>進行加鎖操作後,往縮列圖中添加加鎖文字,並不能得到及時的更新等情況。

    當然不得不說的是,出現這些問題的確是因爲自己對adapter的理解不夠深入,也一直沒有注意這些問題,之前用的還是好好的,所以也就沒有太在意,直到這次遇到問題了,不解決不行。

       下面先貼上項目中用到的adapter類,再慢慢分析:

public FilePageAdapter(List<HashMap<String, Object>> itemList,
			ListView videoFileListView,List<String> videoFilePath,View controlView,Context context) {
		super();

        mListView = videoFileListView;
        mVideoFilePath = videoFilePath;
        mControlView = controlView;
        mContext = context;
        mInflater = LayoutInflater.from(context);

        if (itemList != null) {
			this.itemList = itemList;
		} else {
			this.itemList = new ArrayList<HashMap<String, Object>>();
		}
		if (selectid != null && selectid.size() != 0) {
			selectid.clear();
		}

		mView = new HashMap<Integer, View>();
		isCheck = new HashMap<Integer, Boolean>();
		isMulChoice = true;

		for (int i = 0; i < itemList.size(); i++) {
			isCheck.put(i, false);
		}
		
	}
	

	public void updateView(String path,Bitmap bitmap){
		Log.d(TAG, "*** updateView();itemList.size is:"+itemList.size()
				+";bitmap is:"+bitmap
				+";path is:"+path);
		
		if (selectid != null && selectid.size() != 0) {
			selectid.clear();
		}
		
		for (int i = 0; i < itemList.size(); i++) {
			isCheck.put(i, false);
		}
		
		if(bitmap != null){
			ImageView mImageView = (ImageView) mListView.findViewWithTag(path);
			if (mListView != null && mImageView != null) {
				mImageView.setImageBitmap(bitmap);
			}
		}
		
		notifyDataSetChanged();
	}   

	@Override
	public int getCount() {
		// TODO Auto-generated method stub
		return itemList.size();
	}

	@Override
	public Object getItem(int position) {
		// TODO Auto-generated method stub
		// return null;
		return mVideoFilePath.get(position);
	}

	@Override
	public long getItemId(int position) {
		// TODO Auto-generated method stub
		return position;
	}
        //全選操作
	public void checkAll() {
		for (int i = 0; i < itemList.size(); i++) {
			isCheck.put(i, true);
		}
		notifyDataSetChanged();
	}
	
	public List<String> selectIdGet(){
		return selectid;
	}
    public void selectIdAdd(String itemString){
    	selectid.add(itemString);
    }
    
    public void selectIdClear(){
    	selectid.clear();
    }
	@Override
	public View getView(final int position, View convertView,
			ViewGroup parent) {
		// TODO Auto-generated method stub
		Log.d(TAG, "*** getView()");
		
		final ViewHolder viewHolder;
		
		if (convertView == null) {
			viewHolder = new ViewHolder();
			
			convertView = mInflater.inflate(R.layout.files_list, null);
			viewHolder.file_lable = (MyImageView) convertView
					.findViewById(R.id.file_lable);

			viewHolder.file_check = (CheckBox) convertView
					.findViewById(R.id.file_check_box);
			viewHolder.fileName = (TextView) convertView
					.findViewById(R.id.file_name);
			viewHolder.fileSize = (TextView) convertView
					.findViewById(R.id.file_size);
			viewHolder.fileData = (TextView) convertView
					.findViewById(R.id.file_data);
			viewHolder.fileTime = (TextView) convertView
					.findViewById(R.id.file_time);
            
			viewHolder.file_lable
					.setOnMeasureListener(new OnMeasureListener() {
						public void onMeasureSize(int width, int height) {
							// TODO Auto-generated method stub
							mPoint.set(width, height);
						}
					});
           
		    convertView.setTag(viewHolder);				
		}else{
			viewHolder = (ViewHolder) convertView.getTag();
		}
		
		viewHolder.fileName.setText((String) itemList.get(position)
				.get(Global.mapFileName));
		viewHolder.fileSize.setText((String) itemList.get(position)
				.get(Global.mapFileSize));
		viewHolder.fileData.setText((String) itemList.get(position)
				.get(Global.mapFileData));
		viewHolder.fileTime.setText((String) itemList.get(position)
				.get(Global.mapFileTime));

		convertView.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				// TODO Auto-generated method stub
				// click the item and playVideo
				String path = new String();
				path = mVideoFilePath.get(position);

				Uri videoPath = Uri.parse(path);
				//播放視頻
				VideoUtil.getInstance(mContext).playVideo(videoPath);
			}
		});
		
		String fileAbsolutePath = Global.defaule_storage_path + "/"
				+ itemList.get(position).get(Global.mapFileName);
		
		//the checkBox's Listener must before the init of checkBox
		viewHolder.file_check.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				CheckBox cb = (CheckBox) v;
				
				if(cb.isChecked()){
					mControlView.setVisibility(View.VISIBLE);
					selectid.add(mVideoFilePath.get(position));
					isCheck.put(position, true);
				}else{
					mControlView.setVisibility(View.GONE);
					selectid.remove(mVideoFilePath.get(position));
					isCheck.remove(position);
				}
			}
		});

		if (isCheck.get(position) != null) {
			Log.d(TAG, "*** isCheck.get(position) is:"+isCheck.get(position));
			
			viewHolder.file_check.setChecked(isCheck.get(position));
		}
		
		viewHolder.file_lable.setTag(fileAbsolutePath);
		
		ifFileLock = itemList.get(position).get(Global.mapFileLock)
				.toString();
		
		Log.d(TAG, "** before NativeVideoThumbnailLoader(); ifFileLock is: "+ifFileLock);
		//異步加載圖片
		Bitmap bitmap = NativeVideoThumbnailLoader.getInstance()
				.loadNativeImage(fileAbsolutePath, mPoint, ifFileLock,
						new NativeImageCallBack() {
							@Override
							public void onImageLoader(Bitmap bitmap,
									String path) {
								Log.d(TAG, "***Callback onImageLoader();path is:"+path
										+";bitmap is:"+bitmap);
								
								ImageView mImageView = (ImageView) mListView
										.findViewWithTag(path);
								if (bitmap != null && mImageView != null) {
									mImageView.setImageBitmap(bitmap);
								}
							}
						});
		Log.e(TAG, "*** after NativeVideoThumbnailLoader: bitmap is:"+bitmap);
		
		if (bitmap != null) {
			viewHolder.file_lable.setImageBitmap(bitmap);
		} else {
			if (ifFileLock.equals(DataBaseUtil.dbFileLock)) {
				viewHolder.file_lable
						.setImageResource(R.drawable.file_video_lock);
			} else {
				viewHolder.file_lable
				        .setImageResource(R.drawable.file_video);
			}
		}
		return convertView;
	}
	
	static class ViewHolder {
		CheckBox file_check;
		TextView fileName;
		TextView fileSize;
		TextView fileData;
		TextView fileTime;

		MyImageView file_lable;
	}
}
         關於adapter原理相關的知識點,相信網上是有一大堆,而且都是分析的很不錯。附上個人覺得不錯關於adapter深入理解和優化的鏈接:點擊打開鏈接 http://mobile.51cto.com/abased-445617.htm。

         而我要說的點,是前面遇到的問題,也是爲了給自己提個醒,下次寫代碼時,代碼質量能得到提高:

         1>使用ViewHolder ,這樣刷新view的時候 就不用每次都去解析 佈局的xml文件;

         2>對checkBox的監聽,需要放在對checkBox 的初始化之前;

         3>對checkBox只需要設置onClick 監聽,不需要設置Change監聽,在onClick監聽中可以通過下面方式直接判斷checkBox的選中狀態

viewHolder.file_check.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				CheckBox cb = (CheckBox) v;
				
				if(cb.isChecked()){
					mControlView.setVisibility(View.VISIBLE);
					selectid.add(mVideoFilePath.get(position));
					isCheck.put(position, true);
				}else{
					mControlView.setVisibility(View.GONE);
					selectid.remove(mVideoFilePath.get(position));
					isCheck.remove(position);
				}
			}
		});
             4>關於增大checkBox的點擊區域,如果只是有一個checkBox的話,可以增大checkBox的背景區域,對checkBox的背景進行監聽,通過設置一個全局變量,通過判斷全局變量的變化,判斷checkBox的選中狀態;

            如果是有多個checkBox的話,就需要設置 集合對相應的position的checkBox的狀態進行記錄,我做了如下的嘗試: 定義的 public HashMap<Integer,Integer> checkBoxPos; 就是用來記錄相應position的checkBox的選中狀態,個人覺得思路是沒有問題,不過測試的過程中,還是出現了checkBox的選中狀態顯示混亂的問題,不過通過log打印,實際的狀態是沒有錯的,只是圖標顯示混亂,而我又找不大原因。所以最後乾脆是直接在原來自定義checkBox的圖片的基礎上增大透明背景。

             

viewHolder.check_box__layout.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
//				CheckBox cb = (CheckBox) v;
				Log.d(TAG, "*** position is:"+position
						+";checkBoxPos.get(position) is:"+ checkBoxPos.get(position));
				
				if(0 == checkBoxPos.get(position)){
					checkBoxPos.put(position,1);
					mControlView.setVisibility(View.VISIBLE);
					selectid.add(mVideoFilePath.get(position));
					isCheck.put(position, true);
					viewHolder.file_check.setBackgroundResource(R.drawable.file_check_on);
				}else{
					checkBoxPos.put(position, 0);
					mControlView.setVisibility(View.GONE);
					selectid.remove(mVideoFilePath.get(position));
					isCheck.remove(position);
					viewHolder.file_check.setBackgroundResource(R.drawable.file_check_off);
				}
			}
		});
        本來是想寫一些關於adapter的原理性的東西,奈何理解不夠深入,也覺得別人寫的的確很好了。在這裏也只是想記錄先自己遇到的問題以及解決的方法,相信只有想我這種菜鳥纔會遇到這種問題吧。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章