android 自定义adapter和线程结合 + ListView中按钮滑动后状态丢失解决办法

adapter+线程

1.很多时候自定义adapter的数据都是来源于服务器的,所以在获取服务器的时候就需要异步获取,这里就需要开线程了(线程池)去获取服务器的数据了。但这样有的时候adapter的中没有数据。

如下面的代码:

这就是在initData中异步获取服务器的数据,然后实例化adatper,再将adapter赋给listView。

2.initData()中的代码是:

这里线程要睡眠5秒钟,是为了模仿网络的耗时操作

3.Handler:

在Handler中接收到数据后给list赋值后,告诉adapter数据改变了,要更改UI 了。

4.自定义中的Myadapter中的一段代码:

这段代码就是想在实例化Myadapter的时候根据数据的长度来new一个对应长度的数组。

5.上面的准备工作完成后运行程序:

报错说明list1.size是没有大小的;

经过验证后得到出错的原因是在这段代码上:

从代码的执行顺序来说,InitData方法在线程当中获取数据后通过handler进行处理后list列表就应该有数据了,但实际上是不会有数据的,因为开辟了线程进行耗时操作,它会继续在线程但中执行,而程序会自己执行下去,在初始化adapter的时候list就为空。所以要将必须是要将initData()异步后去值后在去adapter的初始化和给listView的赋值。就该将adapter和listView.setAdapter(adapter)这段代码放到:

这样就能获取到数据并付给listView 了。

显示的结果就是:

ListView中按钮滑动后状态丢失

上面的效果是出来了,现在又遇到另外一个问题就是checkbox的状态在滑动listview后会丢失

如:

在选中前面三个checkbox后,如果上拉的滑动listview后(至前三个checkbox都看不见了),在下拉去观察前三个checkbox的状态是没有被选中的状态,为什么我选择了状态,现在却没有选中呢?

这里在对listview的一个循环机制做个解释(引用自网络):

我们有大量的数据需要显示的时候,每个Item都去重复执行getView中的创建新的View的动作吗?这样做会耗费大量的资源去执行重复的事情,实际上Android为我们提供了一套重复利用的机制叫做“Recycler”:

原理简单描述下就是这样:


一个完整的ListView第一次出现时,每个Item都是Null的,getView的时候会跑到需要inflate一个Item的代码段,假设整个
view只能最多显示10个item,那么当滑动到第11个Item的时候,第一个item会放入“recycler”,如果第11个Item和放入
“Recycler”的item的view一致,那么就会使用"Recycler"里面的Item来显示,从而不用再重复inflate一次,这样大大节
省了创建View的工作,在需要显示大量数据时显得尤为重要

所以在listview重新引入item之前,就必须要将item中每个checkd 状态就要被记录下来:

对adapter中getView()的:

对ViewHolder进行一个解释:

就是一个持有者的类,他里面一般没有方法,只有属性,作用就是一个临时存储器,把你getView方法中每次翻的View存起来,可以下次再用。这样做的好处就是不必每次都到布局文件中去拿你的View,提高了效率

这里先对checks状态数组的长度初始化为list的长度,然后再getView()绘制listView的item的时候按顺序执行下来,如果checkBox的状态被改变了就记录到数组当中,而数组的下标就是item的位置。

在设置checkbox状态时,就直接根据对应数组中下标为Position的值。就OK了

这样就改变了滑动按钮状态丢失的情况。

这里发一个完整的代码:


  1 public class MainActivity extends Activity {
2
3 private ListView listView;
4
5 Madapter adapter;
6 private List<HashMap<String, Object>> list;
7
8 private static final int LDADDATA = 0;
9
10 @Override
11 protected void onCreate(Bundle savedInstanceState) {
12 super.onCreate(savedInstanceState);
13 setContentView(R.layout.activity_main);
14 listView = (ListView) findViewById(R.id.listView);
15 initData();
16 //从代码的执行顺序来说,InitData方法在线程当中获取数据后通过handler进行处理后list列表就应该有数据了,但实际上是不会有数据的,
17 //因为开辟了线程进行耗时操作,它会继续在线程但中执行,而程序会自己执行下去,在初始化adapter的时候list就为空
18 // adapter = new Madapter(MainActivity.this, R.layout.item, list);
19 // listView.setAdapter(adapter);
20 }
21
22 static class ViewHolder {
23 TextView title;
24 CheckBox checkBox;
25 }
26
27 private void initData() {
28 list = new ArrayList<HashMap<String, Object>>();
29 final List<HashMap<String, Object>> list1 = new ArrayList<HashMap<String, Object>>();
30 new Thread(new Runnable() {
31
32 @Override
33 public void run() {
34 try {
35 Thread.sleep(5000);
36
37 } catch (InterruptedException e) {
38 // TODO Auto-generated catch block
39 }
40 for (int i = 0; i < 20; i++) {
41 HashMap<String, Object> map = new HashMap<String, Object>();
42 map.put("title", "title" + i);
43 list1.add(map);
44 }
45 Message message = myHandler.obtainMessage(LDADDATA);
46 message.obj = list1;
47 message.sendToTarget();
48 }
49 }).start();
50
51 }
52
53 public Handler myHandler = new Handler() {
54 public void handleMessage(Message msg) {
55 switch (msg.arg1) {
56 case LDADDATA:
57 list = (List<HashMap<String, Object>>) msg.obj;
58 adapter = new Madapter(MainActivity.this, R.layout.item, list);
59 listView.setAdapter(adapter);
60 break;
61 default:
62 break;
63
64 }
65
66 };
67
68 };
69 public class Madapter extends BaseAdapter {
70 private int resource;
71 private LayoutInflater inflater;
72 private boolean[] checks;
73
74 public Madapter(Context context, int resource,
75 List<HashMap<String, Object>> list1) {
76 checks = new boolean[list1.size()];
77 this.resource = resource;
78 inflater = (LayoutInflater) context
79 .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
80 System.out.println("LIST的长度---->>" + list.size());
81 }
82
83 @Override
84 public int getCount() {
85 return list.size();
86 }
87
88 @Override
89 public Object getItem(int position) {
90 return list.get(position);
91 }
92
93 @Override
94 public long getItemId(int position) {
95 return position;
96 }
97
98 @Override
99 public View getView(int position, View convertView, ViewGroup parent) {
100 System.out.println("这句话执行了的");
101 ViewHolder holder = null;
102 if (convertView == null) {
103 convertView = inflater.inflate(resource, null);
104 holder = new ViewHolder();
105 holder.title = (TextView) convertView.findViewById(R.id.title);
106 holder.checkBox = (CheckBox) convertView
107 .findViewById(R.id.checkBox);
108 convertView.setTag(holder);
109
110 } else {
111 holder = (ViewHolder) convertView.getTag();
112 }
113 holder.title.setText(list.get(position).get("title").toString());
114 final int pos = position;
115 holder.checkBox
116 .setOnCheckedChangeListener(new CheckBox.OnCheckedChangeListener() {
117
118 @Override
119 public void onCheckedChanged(CompoundButton buttonView,
120 boolean isChecked) {
121 checks[pos] = isChecked;
122 System.out.println(isChecked);
123 }
124 });
125 holder.checkBox.setChecked(checks[pos]);
126
127 return convertView;
128 }
129
130 }
131
132 @Override
133 public boolean onCreateOptionsMenu(Menu menu) {
134 getMenuInflater().inflate(R.menu.main, menu);
135 return true;
136 }
137
138 }

ListView状态丢失的扩展情况分析:


这时你就必须先将获得的按钮初始状态保存到对应的数组当中去,这里自己做个笔记:


  1 public View getView(int position, View convertView, ViewGroup parent) {
2 final HashMap<String, Object> map = items.get(position);
3 ViewHolder holder = null;
4 if (convertView == null) {
5 convertView = inflater.inflate(R.layout.moniter_item, null);
6 holder = new ViewHolder();
7 holder.temperture = (TextView) convertView
8 .findViewById(R.id.tempure_now);
9 holder.moist = (TextView) convertView
10 .findViewById(R.id.moist_now);
11 holder.soilTemperature = (TextView) convertView
12 .findViewById(R.id.soilTemperature_now);
13 holder.photosynthetic = (TextView) convertView
14 .findViewById(R.id.photosynthetic_now);
15 holder.soilhumidity = (TextView) convertView
16 .findViewById(R.id.soilumidity_now);
17 holder.radiation = (TextView) convertView
18 .findViewById(R.id.radiation_now);
19 holder.carbondioxide = (TextView) convertView
20 .findViewById(R.id.carbondioxide_now);
21 holder.lanName = (TextView) convertView
22 .findViewById(R.id.lan_num);
23 holder.sluiceToggButton = (ToggleButton) convertView
24 .findViewById(R.id.sluice);
25 holder.rollerToggButton = (ToggleButton) convertView
26 .findViewById(R.id.roller);
27 convertView.setTag(holder);
28 } else {
29 holder = (ViewHolder) convertView.getTag();
30 }
31
32 final int pos = position;
33
34 // View view1 = RealtimeMoniterActivity.this.getLayoutInflater()
35 // .inflate(R.layout.moniter_item, null);// 消息
36
37 holder.temperture.setText(map.get("tempture").toString());
38 holder.moist.setText(map.get("moist").toString());
39 holder.soilTemperature.setText(map.get("soilTemperature")
40 .toString());
41 holder.photosynthetic.setText(map.get("photosynthetic").toString());
42 holder.soilhumidity.setText(map.get("soilhumidity").toString());
43 holder.radiation.setText(map.get("radiation").toString());
44 holder.carbondioxide.setText(map.get("carbondioxide").toString());
45 holder.lanName.setText(map.get("realDataAreaName").toString());
46
47 if (map.get("sluice").toString().equals("0")) {
48 sluiceCheck[pos] = false;
49 } else {
50 sluiceCheck[pos] = true;
51 }
52
53 if (map.get("roller").toString().equals("0")) {
54 rollerCheck[pos] = false;
55 } else {
56 rollerCheck[pos] = true;
57 }
58
59 holder.sluiceToggButton
60 .setOnCheckedChangeListener(new ToggleButton.OnCheckedChangeListener() {
61
62 @Override
63 public void onCheckedChanged(CompoundButton buttonView,
64 boolean isChecked) {
65
66 sluiceCheck[pos] = isChecked; //记录那个位置的toggbutton的状态改变成什么了;
67 if (isChecked) {
68 commandBase.request(new TaskListener() {
69
70 @Override
71 public void updateCacheDate(
72 List<HashMap<String, Object>> cacheData) {
73
74 }
75
76 @Override
77 public void start() {
78 }
79
80 @Override
81 public String requestUrl() {
82 return "updateStatus";
83 }
84
85 @Override
86 public JSONObject requestData() {
87
88 JSONObject object1 = new JSONObject();
89 try {
90 object1.put("id", map.get("id"));
91 object1.put("sluice", 1);
92 object1.put("roller",
93 (Integer) map.get("roller"));
94 } catch (JSONException e) {
95 e.printStackTrace();
96 }
97
98 return object1;
99 }
100
101 @Override
102 public String readCache() {
103 return null;
104 }
105
106 @Override
107 public boolean needCacheTask() {
108 return false;
109 }
110
111 @Override
112 public void messageUpdated(JSONObject msg) {
113 }
114
115 @Override
116 public void finish() {
117 }
118
119 @Override
120 public String filepath() {
121 return null;
122 }
123
124 @Override
125 public void failure(String str) {
126
127 }
128
129 @Override
130 public String contentype() {
131 return null;
132 }
133 });
134
135 map.put("sluice", 1); //因为不会自动去刷新map中的数据,所以在下拉,
136 //上拉滑动是从原来List<HashMap<.,.>>获取数据,这样就造成了状态药恢复到没改变前的状态,所以就必须去修改map中的对应的状态,
137 //这样在滑动的时候就获取的List<HashMap<.,.>>的数据就是已经改变过了,如果有自动刷新的按钮,这些问题就不会存在了
138
139 } else {
140
141 commandBase.request(new TaskListener() {
142
143 @Override
144 public void updateCacheDate(
145 List<HashMap<String, Object>> cacheData) {
146
147 }
148
149 @Override
150 public void start() {
151
152 }
153
154 @Override
155 public String requestUrl() {
156 return "updateStatus";
157 }
158
159 @Override
160 public JSONObject requestData() {
161
162 JSONObject object1 = new JSONObject();
163 try {
164 object1.put("id", map.get("id"));
165 object1.put("sluice", 0);
166 object1.put("roller",
167 (Integer) map.get("roller"));
168 } catch (JSONException e) {
169 e.printStackTrace();
170 }
171
172 return object1;
173 }
174
175 @Override
176 public String readCache() {
177 return null;
178 }
179
180 @Override
181 public boolean needCacheTask() {
182 return false;
183 }
184
185 @Override
186 public void messageUpdated(JSONObject msg) {
187 }
188
189 @Override
190 public void finish() {
191
192 }
193
194 @Override
195 public String filepath() {
196 return null;
197 }
198
199 @Override
200 public void failure(String str) {
201
202 }
203
204 @Override
205 public String contentype() {
206 return null;
207 }
208 });
209 map.put("sluice", 0);//因为不会自动去刷新map中的数据,所以在下拉,
210 //上拉滑动是从原来List<HashMap<.,.>>获取数据,这样就造成了状态药恢复到没改变前的状态,所以就必须去修改map中的对应的状态,
211 //这样在滑动的时候就获取的List<HashMap<.,.>>的数据就是已经改变过了,如果有自动刷新的按钮,这些问题就不会存在了
212 }
213 }
214 });
215
216 holder.rollerToggButton
217 .setOnCheckedChangeListener(new ToggleButton.OnCheckedChangeListener() {
218
219 @Override
220 public void onCheckedChanged(CompoundButton buttonView,
221 boolean isChecked) {
222 rollerCheck[pos] = isChecked;
223
224 if (isChecked) {
225 commandBase.request(new TaskListener() {
226
227 @Override
228 public void updateCacheDate(
229 List<HashMap<String, Object>> cacheData) {
230
231 }
232
233 @Override
234 public void start() {
235
236 }
237
238 @Override
239 public String requestUrl() {
240 return "updateStatus";
241 }
242
243 @Override
244 public JSONObject requestData() {
245 JSONObject object1 = new JSONObject();
246 try {
247 object1.put("id", map.get("id"));
248 object1.put("sluice",
249 (Integer) map.get("sluice"));
250 object1.put("roller", 1);
251 } catch (JSONException e) {
252 e.printStackTrace();
253 }
254
255 return object1;
256 }
257
258 @Override
259 public String readCache() {
260 return null;
261 }
262
263 @Override
264 public boolean needCacheTask() {
265 return false;
266 }
267
268 @Override
269 public void messageUpdated(JSONObject msg) {
270 System.out.println("返回的数据--->>"
271 + msg.toString());
272
273 }
274
275 @Override
276 public void finish() {
277
278 }
279
280 @Override
281 public String filepath() {
282 return null;
283 }
284
285 @Override
286 public void failure(String str) {
287
288 }
289
290 @Override
291 public String contentype() {
292 return null;
293 }
294 });
295 map.put("roller", 1);//因为不会自动去刷新map中的数据,所以在下拉,
296 //上拉滑动是从原来List<HashMap<.,.>>获取数据,这样就造成了状态药恢复到没改变前的状态,所以就必须去修改map中的对应的状态,
297 //这样在滑动的时候就获取的List<HashMap<.,.>>的数据就是已经改变过了,如果有自动刷新的按钮,这些问题就不会存在了
298 } else {
299 commandBase.request(new TaskListener() {
300
301 @Override
302 public void updateCacheDate(
303 List<HashMap<String, Object>> cacheData) {
304
305 }
306
307 @Override
308 public void start() {
309
310 }
311
312 @Override
313 public String requestUrl() {
314 return "updateStatus";
315 }
316
317 @Override
318 public JSONObject requestData() {
319 JSONObject object1 = new JSONObject();
320 try {
321 object1.put("id", map.get("id"));
322 object1.put("sluice",
323 (Integer) map.get("sluice"));
324 object1.put("roller", 0);
325 } catch (JSONException e) {
326 e.printStackTrace();
327 }
328
329 return object1;
330 }
331
332 @Override
333 public String readCache() {
334 return null;
335 }
336
337 @Override
338 public boolean needCacheTask() {
339 return false;
340 }
341
342 @Override
343 public void messageUpdated(JSONObject msg) {
344 System.out.println("返回的数据--->>"
345 + msg.toString());
346 }
347
348 @Override
349 public void finish() {
350
351 }
352
353 @Override
354 public String filepath() {
355 return null;
356 }
357
358 @Override
359 public void failure(String str) {
360
361 }
362
363 @Override
364 public String contentype() {
365 return null;
366 }
367 });
368 map.put("roller", 0);//因为不会自动去刷新map中的数据,所以在下拉,
369 //上拉滑动是从原来List<HashMap<.,.>>获取数据,这样就造成了状态药恢复到没改变前的状态,所以就必须去修改map中的对应的状态,
370 //这样在滑动的时候就获取的List<HashMap<.,.>>的数据就是已经改变过了,如果有自动刷新的按钮,这些问题就不会存在了
371
372 }
373
374 }
375 });
376
377 holder.sluiceToggButton.setChecked(sluiceCheck[pos]);
378 holder.rollerToggButton.setChecked(rollerCheck[pos]);
379
380 return convertView;
381 }
382 }

android 自定义adapter和线程结合 + ListView中按钮滑动后状态丢失解决办法,布布扣,bubuko.com

时间: 2024-10-13 04:19:26

android 自定义adapter和线程结合 + ListView中按钮滑动后状态丢失解决办法的相关文章

android listview + checkbox 列表上下滑动导致复选框状态丢失解决办法

以前为这个问题头疼很久.然后去忙其他事情.一直没有去整理,今天好不容易闲下来.就来整整这个listview + checkbox的问题吧 界面: listview_cell: 界面很简单,一个全屏的listview,cell很简单,一个textview一个checkbox activity: package com.example.testlistviewandcheckbox; import java.util.ArrayList; import java.util.List; import

Android真机调试的时候logcat中无法输出调试信息的解决办法

真机调试不输出日志到logcat的原因是手机厂商默认关闭了调试打印的功能,通过以下方法开启此方法. 下面以华为P6手机为例进行操作: 1.在拨号界面输入:*#*#2846579#*#* 进入测试菜单界面. 2.工程菜单–后台设置–LOG设置 3.LOG开关–LOG打开 OK至此设置完毕,手机会自动重启以下,然后就可以用了 对于别的手机可能还会需要以下两步: 4.LOG级别设置–VERBOSE 5.Dump&Log– 全部选中

【转】Android自定义Adapter的ListView的思路及代码

原文网址:http://www.jb51.net/article/37236.htm Android自定义Adapter的ListView的思路及代码,需要的朋友可以参考一下 在开发中,我们经常使用到ListView这个控件.Android的API也提供了许多创建ListView适配器的快捷方式.例如ArrayAdapter.SimpleAdapter和SimpleCursorAdapter等.但你是否发现,如果采用这些系统自带的适配器,对于事件的响应只能局限在一个行单位.假设一行里面有一个按钮

Android 自定义Adapter 但listview 只显示第一条数据

楼主让这个问题郁闷了一晚上.....在logcat里明明显示adapter的getview方法里的list大于一条数据 ,但posotion却一直是0.....运行后也只显示list[0]里面的数据....最后的最后原来错误出在布局文件上 我以前的是这样的; <ScrollView android:layout_width="fill_parent" android:layout_height="wrap_content" > <!-- listv

Android 自定义Adapter实现多视图Item的ListView

自定义Adapter实现多视图Item的ListView http://www.devdiv.com/adapter_item_listview-blog-20-7539.html Android 自定义Adapter实现多视图Item的ListView,布布扣,bubuko.com

Android新浪微博客户端(七)——ListView中的图片异步加载、缓存

原文出自:方杰|http://fangjie.sinaapp.com/?p=193转载请注明出处 最终效果演示:http://fangjie.sinaapp.com/?page_id=54该项目代码已经放到github:https://github.com/JayFang1993/SinaWeibo 一.ListView的图片异步加载 我们都知道对每一个Weibo Item都有用户头像,而且每一条微博还可能带有图片.如果在加载列表的同时加载图片,这样有几个缺点,第一很费事,界面卡住,用户体验很不

Android自定义组件系列【10】——随ViewPager滑动的导航条

昨天在用到ViewPager实现滑动导航的时候发现微信的导航条效果是跟随ViewPager的滑动而动的,刚开始想了一下,感觉可以使用动画实现,但是这个滑动是随手指时时变化的,貌似不可行,后来再网上搜了一下,找到一个开源代码,结果打开一看大吃一惊,这么简单的效果代码居然大概有300多行,太占手机存储空间了!后来自己干脆重写ViewGroup使用scrollTo方法实现了一下,具体实现过程如下: package com.example.slideupdownviewpage; import andr

C#:使用ListView动态添加数据一直闪烁的解决办法

首先,自定义一个类ListViewNF,继承自 System.Windows.Forms.ListView using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Forms; namespace 你的名称空间 { class ListViewNF : System.Windows.Forms.ListView { public ListV

20170514002Oracle 11g R2安装过程中遇到的报错及解决办法

Oracle 11g R2安装过程中遇到的报错及解决办法 1.提示Check if the DISPLAYvariable is set.    Failed<<<< 解决方案: #xhost +  //切换到root用户输入 #su – Oracle  //切换到oracle用户 $./runInstaller  //执行安装程序 xhost 是用来控制X server访问权限的. 通常当你从hostA登陆到hostB上运行hostB上的应用程序时, 做为应用程序来说,hostA