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 > |