Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android中Adapter中edittext,checkbox記住狀態解決方案(二)

Android中Adapter中edittext,checkbox記住狀態解決方案(二)

編輯:關於Android編程

\

Android中Adapter中edittext,checkbox記住狀態解決方案(一)

在上篇文章解決了adapter中checkbox記住狀態和edittext可編輯的問題,下面談談怎麼解決記住edittext中的內容和保證在操作加、減按鈕的時候,操作的edittext對象是沒有錯位的問題。

一、記住edittext中的內容

解決的思路和checkbox差不多,不過還是有些差別,checkbox只有兩種狀態,而edittext的值是不固定的。checkbox我們是用一個enum類型的list來保存狀態的,所以edittext就不能了,可以用map和實體類,我為了方便就用了hashMap。

 

// 用來存儲editext中數據的list
private List> mData = new ArrayList>();
在初始化的時候先模擬數據

 

 

	for (CartBean cartBean : list) {
			mData.add(new HashMap());
		}

 

edittext的監聽,並且有個log

            mHolder.num.addTextChangedListener(new TextWatcher() {

			@Override
			public void onTextChanged(CharSequence s, int start, int before,
					int count) {
		
			}

			@Override
			public void beforeTextChanged(CharSequence s, int start, int count,
					int after) {

			}

			@Override
			public void afterTextChanged(Editable s) {
				if (!TextUtils.isEmpty(s.toString())) {
                                     
					if(!TextUtils.isEmpty(s.toString())){
						mData.get(position).put(etValue,
								s.toString());
						 Log.i(afterTextChanged, position+position);
					}
				}
			}
		});
根據list對應位置的position取出edittext的值

 

 

       String value = mData.get(position).get(etValue);
		if (!TextUtils.isEmpty(value)) {
			mHolder.num.setText(value);
		} else {
			mHolder.num.setText(1);
		}
代碼出來了,然後在測試的時候可以發現仍然會出現錯亂的問題,後來當多次來回滑動列表之後,再滑動列表,讓第一個剛好完全出來,下一個剛好進來,這時候第一個item會被剛進來的item重用,執行上面的賦值代碼的時候log應該是這樣

 

 

01-27 15:55:46.612: I/afterTextChanged(4784): position0
01-27 15:55:46.622: I/afterTextChanged(4784): position1
01-27 15:55:46.632: I/afterTextChanged(4784): position2
01-27 15:55:46.642: I/afterTextChanged(4784): position3
01-27 15:55:46.642: D/AbsListView(4784): unregisterIRListener() is called 
01-27 15:55:46.642: D/AbsListView(4784): unregisterIRListener() is called 
01-27 15:55:46.662: D/AbsListView(4784): unregisterIRListener() is called 
01-27 15:55:46.682: D/AbsListView(4784): unregisterIRListener() is called 
01-27 15:55:56.882: I/afterTextChanged(4784): position4

一個操作只觸發一個監聽

 

結果發現是這樣

 

01-27 15:53:43.772: I/afterTextChanged(4784): position0
01-27 15:53:43.772: I/afterTextChanged(4784): position5
01-27 15:53:43.772: I/afterTextChanged(4784): position5
01-27 15:53:43.772: I/afterTextChanged(4784): position9
01-27 15:53:43.772: I/afterTextChanged(4784): position5
01-27 15:53:43.772: I/afterTextChanged(4784): position0
01-27 15:53:43.772: I/afterTextChanged(4784): position6
01-27 15:53:43.772: I/afterTextChanged(4784): position15
01-27 15:53:43.772: I/afterTextChanged(4784): position15
01-27 15:53:43.772: I/afterTextChanged(4784): position11
01-27 15:53:43.772: I/afterTextChanged(4784): position6
01-27 15:53:43.772: I/afterTextChanged(4784): position2
01-27 15:53:43.772: I/afterTextChanged(4784): position8
01-27 15:53:43.772: I/afterTextChanged(4784): position12
01-27 15:53:43.772: I/afterTextChanged(4784): position18
01-27 15:53:43.772: I/afterTextChanged(4784): position13
01-27 15:53:43.772: I/afterTextChanged(4784): position9
01-27 15:53:43.772: I/afterTextChanged(4784): position4
01-27 15:53:43.772: I/afterTextChanged(4784): position4
一個操作觸發了很多個監聽,觸發了多個監聽,就必然會導致多個地方的edittext的值被改變,所以才出現錯亂的問題。後來我想到可能是在adapter反復執行

 

 

  mHolder.num.addTextChangedListener(new TextWatcher()
的緣故,為了證實自己的想法,我點進去看了下監聽的源碼,發現

 

 

 public void addTextChangedListener(TextWatcher watcher) {
        if (mListeners == null) {
            mListeners = new ArrayList();
        }

        mListeners.add(watcher);
    }
原來android是用了arraylist把所有加進來的監聽都存起來了,所以才會有一個操作觸發多個監聽的問題。那麼checkbox沒出現這樣的原因應該是每次都重新設置監聽對象了吧

 

 

 public void setOnClickListener(OnClickListener l) {
        if (!isClickable()) {
            setClickable(true);
        }
        getListenerInfo().mOnClickListener = l;
    }
果然每次都重新設置一個新的。其實根據方法名能夠看出來方法的用途的,一個是add,一個是set。
問題找到那就好辦了,其實adapter中的viewholder對象數目是固定的,在多也只會重用了,所以我們也可以設置和viewholder一樣數量的監聽就行了,可以這樣做

 

 

if (convertView == null) {
      ....
      class MyTextWatcher implements TextWatcher {
		public MyTextWatcher() {}


		       @Override
			public void onTextChanged(CharSequence s, int start,
				int before, int count) {
			}

		       @Override
			public void beforeTextChanged(CharSequence s, int start,
				int count, int after) {
			}

			@Override
			public void afterTextChanged(Editable s) {
				if (!TextUtils.isEmpty(s.toString())) {
					mData.get(position).put(etValue, s.toString()); //
					Log.i(afterTextChanged, position + position);
				}
		       }
	}

			mHolder.num.addTextChangedListener(new MyTextWatcher(mHolder));
}
這樣只在convertview為null的時候才添加監聽,這樣保證了一個edittext只會有一個監聽。再試試,發現還是不對,改變過的值都無法保存。出了問題還是看log

 

 

01-27 16:59:40.512: I/afterTextChanged(12344): position0
01-27 16:59:40.532: I/afterTextChanged(12344): position1
01-27 16:59:40.542: I/afterTextChanged(12344): position2
01-27 16:59:40.552: I/afterTextChanged(12344): position3
01-27 16:59:42.772: I/afterTextChanged(12344): position4
01-27 16:59:43.712: I/afterTextChanged(12344): position0
01-27 16:59:44.502: I/afterTextChanged(12344): position1
01-27 16:59:45.392: I/afterTextChanged(12344): position2
01-27 16:59:46.632: I/afterTextChanged(12344): position3
01-27 16:59:47.492: I/afterTextChanged(12344): position4
01-27 16:59:47.842: I/afterTextChanged(12344): position0
01-27 16:59:49.142: I/afterTextChanged(12344): position1
01-27 16:59:51.662: I/afterTextChanged(12344): position2
01-27 16:59:52.822: I/afterTextChanged(12344): position3
01-27 16:59:53.192: I/afterTextChanged(12344): position4
01-27 17:00:06.662: I/afterTextChanged(12344): position0
看到監聽裡面的position的值是0-4,也就是說無論列表怎麼滑動,position的值都只是convertview為空的時候初始化好的。這樣當第一項滾出屏幕,底下一項進入屏幕的時候,執行到這段代碼

 

 

//這時代碼position肯定是大於4的,假設是5,但mData中位置為5的地方是空值,這就導致第一項和第6項就都被設為1了
String value = mData.get(position).get(etValue);
		if (!TextUtils.isEmpty(value)) {
			mHolder.num.setText(value);
		} else {
			mHolder.num.setText(1);
		}
想解決這個問題,就得在監聽回調的方法裡能夠動態獲取到position的值。這裡我們可以這樣做

 

 

        if (convertView == null) {
			......

			class MyTextWatcher implements TextWatcher {
				public MyTextWatcher(ViewHolder holder) {
					mHolder = holder;
				}

				/**
				 * 這裡其實是緩存了一屏數目的viewholder, 也就是說一屏能顯示10條數據,那麼內存中就會有10個viewholder
				 * 在這的作用是通過edittext的tag拿到對應的position,用於儲存edittext的值
				 */
				private ViewHolder mHolder;

				@Override
				public void onTextChanged(CharSequence s, int start,
						int before, int count) {
				}

				@Override
				public void beforeTextChanged(CharSequence s, int start,
						int count, int after) {
				}

				@Override
				public void afterTextChanged(Editable s) {
					if (!TextUtils.isEmpty(s.toString())) {
						//通過tag來取position
					 int position = (Integer) mHolder.num.getTag();
						mData.get(position).put(etValue, s.toString()); //
						Log.i(afterTextChanged, position + position);
					}
				}
			}

			mHolder.num.addTextChangedListener(new MyTextWatcher(mHolder));

			convertView.setTag(mHolder);
		} else {
			mHolder = (ViewHolder) convertView.getTag();
		}
       //每次用position動態更新edittext的tag
       mHolder.num.setTag(position);
雖然viewholder就固定的那幾個,但是我們可以通過edittext的tag從而達到動態更新position值的效果。

 

然後再測試就會發現edittext能夠記住內容了。

二、保證在操作加、減按鈕的時候,操作的edittext對象是沒有錯位的

正常監聽是這樣寫

 

mHolder.add.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				strNum = mData.get(position).get(etValue);
				int intnum = Integer.parseInt(strNum);
				intnum++;
				mHolder.num.setText( + intnum);
			}
		});
但這樣寫在adapter中是行不通的,因為當觸發回調的時候,edittext已經不是add按鈕注冊監聽時候的那個了,而是最後一個加載的item中的edittext。edittext的對象已經變了就是導致操作edittext錯位的根本原因。這個問題的解決方法我在上篇文章裡面已經說過了,就是把edittext存起來。代碼我就不貼了,下面我會貼出demo鏈接,感興趣的可以下載看看。有什麼好的建議可以留言分享出來,共同學習。

 

 

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved