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     }
posted @ 2014-05-29 21:44  perfect亮  阅读(2620)  评论(1编辑  收藏  举报