http://www.open-open.com/lib/view/open1336025355359.html
最近在学习Android ,listview会经常使用到.做了些测试.有问题请指正.大家一起讨论.
ListviewTest.java Activity类
001 | import java.util.ArrayList; |
002 | import java.util.LinkedHashMap; |
003 | import java.util.List; |
004 | import java.util.Random; |
005 | |
006 | import android.app.Activity; |
007 | import android.os.Bundle; |
008 | import android.os.Handler; |
009 | import android.os.Message; |
010 | import android.util.Log; |
011 | import android.view.LayoutInflater; |
012 | import android.view.View; |
013 | import android.view.View.OnClickListener; |
014 | import android.view.ViewGroup; |
015 | import android.widget.AbsListView; |
016 | import android.widget.AbsListView.OnScrollListener; |
017 | import android.widget.BaseAdapter; |
018 | import android.widget.Button; |
019 | import android.widget.ListView; |
020 | import android.widget.ProgressBar; |
021 | import android.widget.TextView; |
022 | |
023 | public class ListviewTest extends Activity implements OnClickListener{ |
024 | |
025 | int jobcounter = 0 ; |
026 | |
027 | private static final int ADDJOB = 1001 ; |
028 | private static final int PROCESSADD = 1002 ; |
029 | private static final int PROCESSDONE = 1003 ; |
030 | private static final int ITEMBUTTON_CLICKED = 1004 ; |
031 | |
032 | private static final String TAG = "ListviewTest" ; |
033 | |
034 | protected static final long REFRESH_INTERVAL = 100 ; |
035 | |
036 | protected boolean mBusy = false ; |
037 | long lastupdatetime = 0 ; |
038 | |
039 | |
040 | Object lock = new Object() ; |
041 | |
042 | ListView listview ; |
043 | Button buttonadd ; |
044 | |
045 | AddjavaListAdapter adapter ; |
046 | LayoutInflater inflater ; |
047 | |
048 | LinkedHashMap<Integer, ListInfo> listdatas ; |
049 | |
050 | LinkedHashMap<Integer, ListInfo> addlist = new LinkedHashMap<Integer, ListviewTest.ListInfo>() ; |
051 | List<Integer> delidlist = new ArrayList<Integer>() ; |
052 | |
053 | |
054 | Handler mainhandler = new Handler(){ |
055 | |
056 | public void handleMessage(android.os.Message msg) { |
057 | long v = System.currentTimeMillis() - lastupdatetime ; |
058 | |
059 | |
060 | switch (msg.what) { |
061 | case ADDJOB: |
062 | |
063 | //if (inView(msg.arg1) && !mBusy) { |
064 | // Log.i(TAG, " ADDJOB done!") ; |
065 | updateListView(); |
066 | lastupdatetime += REFRESH_INTERVAL ; |
067 | //} |
068 | break ; |
069 | case PROCESSADD: |
070 | if ( !mBusy && v>REFRESH_INTERVAL) { |
071 | updateListView(); |
072 | lastupdatetime = System.currentTimeMillis() ; |
073 | } |
074 | break ; |
075 | |
076 | case ITEMBUTTON_CLICKED:{ |
077 | if (!listdatas.get(msg.arg1).running ) { |
078 | synchronized (listdatas.get(msg.arg1).lock) { |
079 | listdatas.get(msg.arg1).lock.notifyAll() ; |
080 | } |
081 | } |
082 | listdatas.get(msg.arg1).running = !listdatas.get(msg.arg1).running ; |
083 | if ( !mBusy ) { |
084 | updateListView(); |
085 | lastupdatetime += REFRESH_INTERVAL ; |
086 | } |
087 | break ; |
088 | } |
089 | case PROCESSDONE: |
090 | // Log.i(TAG, " PROCESSDONE done!"+msg.arg1) ; |
091 | synchronized (lock) { |
092 | delidlist.add(msg.arg1) ; |
093 | } |
094 | updateListView(); |
095 | lastupdatetime += REFRESH_INTERVAL ; |
096 | break ; |
097 | |
098 | default : |
099 | break ; |
100 | } |
101 | |
102 | }; |
103 | |
104 | }; |
105 | |
106 | void updateListView(){ |
107 | synchronized (lock) { |
108 | for (Integer delid : delidlist) { |
109 | Log.i(TAG, " PROCESSDONE done!" +delid) ; |
110 | listdatas.remove(delid) ; |
111 | } |
112 | listdatas.putAll(addlist) ; |
113 | |
114 | for (ListInfo info : addlist.values()) { |
115 | //启动工作线程 |
116 | new WorkThread( "workthread#" +jobcounter,info).start() ; |
117 | jobcounter++ ; |
118 | } |
119 | //清空 delidlist 和 addlist |
120 | delidlist.clear() ; |
121 | addlist.clear() ; |
122 | } |
123 | adapter.notifyDataSetChanged(); |
124 | } |
125 | |
126 | |
127 | |
128 | @Override |
129 | protected void onCreate(Bundle savedInstanceState) { |
130 | listdatas = new LinkedHashMap<Integer, ListInfo>() ; |
131 | super .onCreate(savedInstanceState); |
132 | setContentView(R.layout.listviewtest); |
133 | |
134 | listview = (ListView) findViewById(R.id.listView001) ; |
135 | adapter = new AddjavaListAdapter(); |
136 | listview.setAdapter(adapter) ; |
137 | //设置 当listview 进行上下拖动操作时的状态 |
138 | listview.setOnScrollListener( new OnScrollListener() { |
139 | |
140 | @Override |
141 | public void onScrollStateChanged(AbsListView view, int scrollState) { |
142 | switch (scrollState) { |
143 | case OnScrollListener.SCROLL_STATE_IDLE: |
144 | mBusy = false ; |
145 | |
146 | break ; |
147 | case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL: |
148 | mBusy = true ; |
149 | break ; |
150 | case OnScrollListener.SCROLL_STATE_FLING: |
151 | mBusy = true ; |
152 | break ; |
153 | } |
154 | } |
155 | |
156 | @Override |
157 | public void onScroll(AbsListView view, int firstVisibleItem, |
158 | int visibleItemCount, int totalItemCount) { |
159 | |
160 | } |
161 | }) ; |
162 | |
163 | |
164 | buttonadd = (Button) findViewById(R.id.button_listaddjob); |
165 | buttonadd.setOnClickListener( this ); |
166 | |
167 | inflater = LayoutInflater.from( this ); |
168 | |
169 | } |
170 | // 存放单条 listview 的数据 |
171 | class ListInfo{ |
172 | @Override |
173 | public String toString() { |
174 | return "ListInfo [index=" + index + ", id=" + id + ", running=" |
175 | + running + ", title=" + title + ", process=" + process |
176 | + "]" ; |
177 | } |
178 | int index ; |
179 | long id ; |
180 | boolean running = true ; |
181 | |
182 | String title ; |
183 | int process ; |
184 | |
185 | Object lock = new Object(); |
186 | } |
187 | |
188 | class ViewHodler{ |
189 | |
190 | |
191 | TextView text ; |
192 | ProgressBar bar ; |
193 | Button button ; |
194 | ItemClickListener listener; |
195 | |
196 | } |
197 | |
198 | // listview的适配器 |
199 | class AddjavaListAdapter extends BaseAdapter { |
200 | |
201 | |
202 | |
203 | @Override |
204 | public int getCount() { |
205 | return listdatas.keySet().size(); |
206 | } |
207 | |
208 | @Override |
209 | public Object getItem( int position) { |
210 | //从 listdata里获取 对应的数据 ,因为有删除的缘故.在有任务完成后 position不等于listdata的key |
211 | Object[] d = listdatas.keySet().toArray() ; |
212 | int c = (Integer)d[position] ; |
213 | // Log.i(TAG, "~~~~~getItem~~position["+position+"] [c="+c+"]") ; |
214 | return listdatas.get(c) ; |
215 | } |
216 | |
217 | @Override |
218 | public long getItemId( int position) { |
219 | return ((ListInfo) this .getItem(position)).id ; |
220 | } |
221 | |
222 | @Override |
223 | public View getView( int position, View v, ViewGroup parent) { |
224 | ViewHodler holder ; |
225 | // 获取单条item 的view对象 |
226 | if (v== null ) { |
227 | v = inflater.inflate(R.layout.listview_item, null ) ; |
228 | holder = new ViewHodler() ; |
229 | |
230 | holder.text = (TextView) v.findViewById(R.id.textView_item) ; |
231 | holder.bar = (ProgressBar) v.findViewById(R.id.progressBar_item); |
232 | holder.button = (Button) v.findViewById(R.id.button_item) ; |
233 | holder.listener = new ItemClickListener() ; |
234 | |
235 | v.setTag(holder) ; |
236 | |
237 | } else { |
238 | holder = (ViewHodler) v.getTag(); |
239 | } |
240 | //将数据显示到每个对应的 view上. |
241 | final ListInfo data = (ListInfo)getItem(position) ; |
242 | |
243 | holder.listener.setId(data.index) ; |
244 | holder.button.setOnClickListener(holder.listener) ; |
245 | |
246 | holder.text.setText(data.title) ; |
247 | holder.bar.setProgress(data.process) ; |
248 | if (data.running) { |
249 | holder.button.setText(R.string.item_stop) ; |
250 | } else { |
251 | holder.button.setText(R.string.item_start) ; |
252 | } |
253 | |
254 | return v; |
255 | } |
256 | |
257 | } |
258 | |
259 | |
260 | class ItemClickListener implements OnClickListener{ |
261 | private int id ; |
262 | |
263 | public void setId( int id) { |
264 | this .id = id; |
265 | } |
266 | |
267 | @Override |
268 | public void onClick(View v) { |
269 | Log.i(TAG, "button clicked! " +id + "|" +listdatas.get(id).running+ "-->" +!listdatas.get(id).running); |
270 | sendMessageToHandler(ITEMBUTTON_CLICKED,id) ; |
271 | } |
272 | |
273 | } |
274 | |
275 | class WorkThread extends Thread{ |
276 | |
277 | ListInfo in ; |
278 | public WorkThread(String name ,ListInfo in){ |
279 | super (name) ; |
280 | this .in = in ; |
281 | } |
282 | |
283 | @Override |
284 | public void run() { |
285 | ListInfo sdata = listdatas.get(in.index) ; |
286 | |
287 | while (sdata.process< 100 ) { |
288 | |
289 | //如果暂停 则等待 |
290 | if (!listdatas.get(in.index).running ) { |
291 | synchronized (listdatas.get(in.index).lock) { |
292 | try { |
293 | listdatas.get(in.index).lock.wait() ; |
294 | } catch (InterruptedException e) { |
295 | e.printStackTrace(); |
296 | } |
297 | } |
298 | } |
299 | //模拟耗时任务操作 |
300 | try { |
301 | Thread.sleep(( int )( 3000 * new Random().nextDouble())); |
302 | } catch (InterruptedException e) { |
303 | e.printStackTrace(); |
304 | } |
305 | sdata.process += new Random().nextInt( 15 )+ 1 ; |
306 | sendMessageToHandler(PROCESSADD,in.index) ; |
307 | } |
308 | //发送任务结束消息 |
309 | if (sdata.process>= 100 ) { |
310 | sendMessageToHandler(PROCESSDONE,in.index) ; |
311 | // Log.i(TAG, this.getName()+"#done") ; |
312 | |
313 | } |
314 | } |
315 | |
316 | } |
317 | |
318 | |
319 | @Override |
320 | public void onClick(View v) { |
321 | switch (v.getId()) { |
322 | case R.id.button_listaddjob:{ |
323 | |
324 | ListInfo info = new ListInfo() ; |
325 | info.title = "file" + jobcounter ; |
326 | info.process = 0 ; |
327 | info.id = jobcounter ; |
328 | info.index = jobcounter ; |
329 | synchronized (lock) { |
330 | addlist.put(jobcounter, info) ; |
331 | } |
332 | sendMessageToHandler(ADDJOB,jobcounter) ; |
333 | |
334 | break ; |
335 | } |
336 | |
337 | default : |
338 | break ; |
339 | } |
340 | } |
341 | |
342 | |
343 | void sendMessageToHandler( int what, int arg1){ |
344 | Message message = mainhandler.obtainMessage() ; |
345 | message.what = what ; |
346 | message.arg1 = arg1 ; |
347 | message.sendToTarget() ; |
348 | } |
349 | |
350 | } |
布局文件 listview_item.xml
01 | <? xml version = "1.0" encoding = "utf-8" ?> |
02 | < LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android" |
03 | android:id = "@+id/listview_item" |
04 | android:layout_width = "match_parent" |
05 | android:layout_height = "wrap_content" |
06 | android:orientation = "horizontal" > |
07 | |
08 | < TextView |
09 | android:id = "@+id/textView_item" |
10 | android:layout_width = "wrap_content" |
11 | android:layout_height = "wrap_content" |
12 | android:layout_gravity = "center_vertical" |
13 | android:text = "TextView" /> |
14 | |
15 | < ProgressBar |
16 | android:id = "@+id/progressBar_item" |
17 | style = "?android:attr/progressBarStyleHorizontal" |
18 | android:layout_width = "wrap_content" |
19 | android:layout_height = "wrap_content" |
20 | android:layout_gravity = "center_vertical" |
21 | android:layout_weight = "0.75" /> |
22 | |
23 | < Button |
24 | android:id = "@+id/button_item" |
25 | android:layout_width = "wrap_content" |
26 | android:layout_height = "wrap_content" |
27 | android:layout_gravity = "center_vertical" |
28 | android:focusable = "false" |
29 | android:text = "@string/start" /> |
30 | |
31 | |
32 | |
33 | </ LinearLayout > |
布局文件 listviewtext.xml
01 | <? xml version = "1.0" encoding = "utf-8" ?> |
02 | < LinearLayout xmlns:android = "http://schemas.android.com/apk/res/android" |
03 | |
04 | android:layout_width = "match_parent" |
05 | android:layout_height = "match_parent" |
06 | android:orientation = "vertical" > |
07 | |
08 | |
09 | < Button |
10 | android:id = "@+id/button_listaddjob" |
11 | android:layout_width = "wrap_content" |
12 | android:layout_height = "wrap_content" |
13 | android:text = "@string/add" /> |
14 | |
15 | < ListView |
16 | android:id = "@+id/listView001" |
17 | android:layout_width = "match_parent" |
18 | android:layout_height = "wrap_content" > |
19 | </ ListView > |
20 | |
21 | </ LinearLayout > |