編輯:關於Android編程
the old view to reuse, if possible. Note: You should check that this view is non-null and of an appropriate type before using. If it is not possible to convert this view to display the correct data, this method can create a new view
利用好 convertView 來重用 View,切忌每次 getView() 都新建。ListView 的核心原理就是重用 View,如果重用 view 不改變寬高,重用View可以減少重新分配緩存造成的內存頻繁分配/回收;
ListView的android:layout_height屬性值設置為fill_parent或者''wrap_content情況不一樣,但是convertView的機制一樣
如果設置為fill_parent:屏幕上顯示出的Item的convertview都為空,向下滑動新產生的Item的convetview都不為空
如果設置為wrap_content:只有第一個Item的convertview為null,其他的不為空
總結:
在初始顯示的時候,每次顯示一個item都調用一次getview方法但是每次調用的時候covertview為空(因為還沒有舊的view),當顯示完了之後。如果屏幕移動了之後,並且導致有些Item(也可以說是view)跑到屏幕外面,此時如果還有新的item需要產生,則這些item顯示時調用的getview方法中的convertview參數就不是null,而是那些移出屏幕的view(舊view),我們所要做的就是將需要顯示的item填充到這些回收的view(舊view)中去,最後注意convertview為null的不僅僅是初始顯示的那些item,還有一些是已經開始移入屏幕但是還沒有view被回收的那些item。
view的setTag和getTag方法其實很簡單,在實際編寫代碼的時候一個view不僅僅是為了顯示一些字符串、圖片,有時我們還需要他們攜帶一些其他的數據以便我們對該view的識別或者其他操作。於是android 的設計者們就創造了setTag(Object)方法來存放一些數據和view綁定,我們可以理解為這個是view 的標簽也可以理解為view 作為一個容器存放了一些數據。而這些數據我們也可以通過getTag() 方法來取出來。
到這裡setTag和getTag大家應該已經明白了。再回到上面的話題,我們通過convertview的setTag方法和getTag方法來將我們要顯示的數據來綁定在convertview上。如果convertview 是第一次展示我們就創建新的Holder對象與之綁定,並在最後通過return convertview 返回,去顯示;如果convertview 是回收來的那麼我們就不必創建新的holder對象,只需要把原來的綁定的holder取出加上新的數據就行了
class ViewHolder{ ImageView img; TextView name; } public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if(convertView==null){ convertView = inflater.inflate(R.layout.list_item, parent, false); holder.img = (ImageView) convertView.findViewById(R.id.img); holder.name = (TextView) convertView.findViewById(R.id.name); holder = new ViewHolder(); convertView.setTag(holder); }else{ holder = (ViewHolder) convertView.getTag(); } //設置holder holder.img.setImageResource(R.drawable.ic_launcher); holder.name.setText(list.get(position).partname); return convertView; }
/** * list滾動監聽 */ listView.setOnScrollListener(new OnScrollListener() { @Override public void onScrollStateChanged(AbsListView view, int scrollState) { if (scrollState == OnScrollListener.SCROLL_STATE_IDLE) {//list停止滾動時加載圖片 loadImage(startPos, endPos);// 異步加載圖片 ,只加載可以看到的圖片 } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { //設置當前屏幕顯示的起始pos和結束pos startPos = firstVisibleItem; endPos = firstVisibleItem + visibleItemCount; if (endPos >= totalItemCount) { endPos = totalItemCount - 1; } } });
listView = (ListView) rootView.findViewById(R.id.fragment_user_info_lisiview); listView.setOnScrollListener(DisplayImageOptionsUtil.getPauseOnScrollListener(this)); listView.setOnItemClickListener(this);
public static PauseOnScrollListener getPauseOnScrollListener(OnScrollListener scrollListener) { PauseOnScrollListener listener = new PauseOnScrollListener(ImageLoader.getInstance(), false, true, scrollListener); return listener; }PauseOnScrollListener的第一個參數指的是圖片加載對象ImageLoader,第二個參數為pauseOnScroll來控制是否在滑動的過程中暫停加載圖片,如果需要暫停則傳true,第三個參數控制猛的滑動界面的時候圖片是否加載。
/** * Constructor * * @param imageLoader {@linkplain ImageLoader} instance for controlling * @param pauseOnScroll Whether {@linkplain ImageLoader#pause() pause ImageLoader} during touch scrolling * @param pauseOnFling Whether {@linkplain ImageLoader#pause() pause ImageLoader} during fling * @param customListener Your custom {@link OnScrollListener} for {@linkplain AbsListView list view} which also * will be get scroll events */ public PauseOnScrollListener(ImageLoader imageLoader, boolean pauseOnScroll, boolean pauseOnFling, OnScrollListener customListener) { this.imageLoader = imageLoader; this.pauseOnScroll = pauseOnScroll; this.pauseOnFling = pauseOnFling; externalListener = customListener; } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { switch (scrollState) { case OnScrollListener.SCROLL_STATE_IDLE: imageLoader.resume(); break; case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL: if (pauseOnScroll) { imageLoader.pause(); } break; case OnScrollListener.SCROLL_STATE_FLING: if (pauseOnFling) { imageLoader.pause(); } break; } if (externalListener != null) { externalListener.onScrollStateChanged(view, scrollState); } }
holder.img.setonClickListener(new onClickListenr)...但是這種寫法每次調用getView時都設置了一個新的onClick事件,效率很低。高效的寫法可以直接在ViewHolder中設置一個position,然後viewHolder implements OnClickListenr:
class ViewHolder implements OnClickListener{ int position; TextView name; public void setPosition(int position){ this.position = position; } @Override public void onClick(View v) { switch (v.getId()){ //XXXX } } } public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if(convertView==null){ convertView = inflater.inflate(R.layout.list_item, parent, false); holder = new ViewHolder(); holder.name = (TextView) convertView.findViewById(R.id.name); holder.name.setOnClickListener(this); convertView.setTag(holder); }else{ holder = (ViewHolder) convertView.getTag(); } //設置holder holder.name.setText(list.get(position).partname); //設置position holder.setPosition(position); return convertView; }
@Override public View getView(int position, View convertView, ViewGroup paramViewGroup) { Object current_event = mObjects.get(position); ViewHolder holder = null; if (convertView == null) { holder = new ViewHolder(); convertView = inflater.inflate(R.layout.row_event, null); holder.ThreeDimension = (ImageView) convertView.findViewById(R.id.ThreeDim); holder.EventPoster = (ImageView) convertView.findViewById(R.id.EventPoster); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } //在這裡進行邏輯判斷,這是有問題的 if (doesSomeComplexChecking()) { holder.ThreeDimention.setVisibility(View.VISIBLE); } else { holder.ThreeDimention.setVisibility(View.GONE); } // 這是設置image的參數,每次getView方法執行時都會執行這段代碼,這顯然是有問題的 RelativeLayout.LayoutParams imageParams = new RelativeLayout.LayoutParams(measuredwidth, rowHeight); holder.EventPoster.setLayoutParams(imageParams); return convertView; }優化後的getView():
@Override public View getView(int position, View convertView, ViewGroup paramViewGroup) { Object object = mObjects.get(position); ViewHolder holder = null; if (convertView == null) { holder = new ViewHolder(); convertView = inflater.inflate(R.layout.row_event, null); holder.ThreeDimension = (ImageView) convertView.findViewById(R.id.ThreeDim); holder.EventPoster = (ImageView) convertView.findViewById(R.id.EventPoster); //設置參數提到這裡,只有第一次的時候會執行,之後會復用 RelativeLayout.LayoutParams imageParams = new RelativeLayout.LayoutParams(measuredwidth, rowHeight); holder.EventPoster.setLayoutParams(imageParams); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } // 我們直接通過對象的getter方法代替剛才那些邏輯判斷,那些邏輯判斷放到別的地方去執行了 holder.ThreeDimension.setVisibility(object.getVisibility()); return convertView; }
(一)前言FaceBook早期開源發布了React Native For IOS,終於在2015年9月15日也發布了ReactNative for Android,雖然A
有朋友在問微信無法發送語音怎麼辦,微信無法語音解決方法有哪些呢?我們最常使用的微信功能就是與好友語音,所以遇到微信不能發送語音這樣故障的朋友一定很著急吧,希
有時候我們保存文件總會用到文件浏覽器功能.那麼今天博主帶大家做一個。那麼開始,浏覽文件,我們就需要寫一個文件工具類。import java.io.File; import
一、Socket通信簡介Android與服務器的通信方式主要有兩種,一是Http通信,一是Socket通信。兩者的最大差異在於,http連接使用的是“請求&m