Android:仿微博Listview与多线程功能(JSON、数据下载、图片加载、Listview、异步任务)

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介:

解析服务端JSON的内容和图片,通过异步任务下载并设置到listview页上,点击listview跳转到详情页。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
public  class  WatchingActivity  extends  Activity  implements  OnClickListener, OnItemClickListener
{
     private  ListView mListView;
     private  HashMap<URL, Bitmap> mCacheMap =  new  HashMap<URL, Bitmap>();
     private  View errorView;
     private  View loadingview;
     private  RelativeLayout errorlayout;
     private  Button btn_netRetry;
     private  View headview;
     private  View footview;
     private  View btn_footviewloading;
     private  TextView btn_loadmore;
     private  int  mPage =  1 ;
     private  BaseAdapter mAdapter;
     private  ArrayList<ItemData> mDataList =  new  ArrayList<ItemData>();
     private  View headviewad;
     private  View imageBtn_refresh;
                                                                  
     /*
      * 创建布局
      * 下载内容
      * 解析内容
      * 下载图片
      * 图片缓存
      * 网络错误页面
      * 网络加载页面
      * 增加页眉
      * 加载更多
      * 页眉响应
      * ListView行跳转
      * 内容页显示详情
      */
                                                                  
     /**
      * 1.适配器判断是否为空,生命周期?还是因为是第一次===========> 复用会导致数据重新刷新,不能在原有数据基础上加载
      * 2.页眉整张图片,则无法直接点击------------------->layout拦截掉了监听
      * 3.加载更多链接不在时result会报错空值--------------->
      * 4.mListView.setOnItemClickListener(this);用这个方法监听ListView无效?========>监听行布局对象
      * 5.顶部刷新按钮为何不响应?
      * 6.行布局的进度条为何找不到?========>已解决
      * 7.include移位就报错==============>没问题
      * 8.控件层次如何改变=============> relative根据xml代码位置
      * 9.setonItemClick  position要减1才能对应?============> 加完headview后,position初始值自动加1
      *
      */
                                                                  
     class  ItemData
     {
         String imageUrl;
         String title;
         String from;
         String time;
         String content;
         public  ItemData(String imageUrl, String title, String from,
                 String time, String content)
         {
             super ();
             this .imageUrl = imageUrl;
             this .title = title;
             this .from = from;
             this .time = time;
             this .content = content;
         }
                                                                       
     }
                                                                  
     class  ViewHolder
     {
         ImageView imageView;
         TextView textView_title;
         TextView textView_from;
         TextView textView_time;
                                                                      
         ProgressBar progressBar_imageLoading;
     }
                                                                  
     @Override
     protected  void  onCreate(Bundle savedInstanceState)
     {
         super .onCreate(savedInstanceState);
         setContentView(R.layout.activity_watching);
                                                                      
         setUI();
                                                                      
     }
     private  void  setUI()
     {
         LayoutInflater inflater = getLayoutInflater();
         headview = inflater.inflate(R.layout.headview,  null );
         footview = inflater.inflate(R.layout.footview,  null );
         btn_footviewloading = footview.findViewById(R.id.footview_loading);
         btn_loadmore = (TextView) footview.findViewById(R.id.btn_loadmore);
         headviewad = headview.findViewById(R.id.imageView_headview_ad);
         imageBtn_refresh = findViewById(R.id.imageBtn_refresh);
                                                                      
         btn_netRetry = (Button) findViewById(R.id.btn_netRetry);
         loadingview = findViewById(R.id.loadingview);
         errorView = findViewById(R.id.errorview);
         mListView = (ListView) findViewById(R.id.listView_watching);
         mListView.addHeaderView(headview); //注意:一定要在setAdapter之前调用,所以一般在找到listview之后就添加
         mListView.addFooterView(footview);
                                                                      
         loadTask();
                                                                      
         //网络连接重试按钮
         btn_netRetry.setOnClickListener( this );
         //分页加载更多
         btn_loadmore.setOnClickListener( this );
         //点击ListView页眉广告
         headviewad.setOnClickListener( this );
         //点击顶部刷新页面
         btn_netRetry.setOnClickListener( this );
         //点击listview跳转
         mListView.setOnItemClickListener( this );
     }
                                                                  
     //按钮点击事件
     @Override
     public  void  onClick(View v)
     {
         switch  (v.getId())
         {
             case  R.id.btn_netRetry:
                 errorView.setVisibility(View.GONE);
                 mPage =  1 ;
                 loadTask();
                 break ;
                                                                              
             case  R.id.btn_loadmore:
                 btn_loadmore.setVisibility(View.INVISIBLE);
                 btn_footviewloading.setVisibility(View.VISIBLE);
                 loadTask();
                 break ;
                                                                              
             case  R.id.imageView_headview_ad:
                 Toast.makeText(WatchingActivity. this , Contant.HEADVIEW_TOAST, Toast.LENGTH_LONG).show();
                 break ;
                                                                              
             case  R.id.imageBtn_refresh:
                 loadTask();
                 break ;
                                                                              
             default :
                 break ;
         }
     }
                                                                  
     //监听listview
     @Override
     public  void  onItemClick(AdapterView<?> parent, View view,  int  position,
             long  id)
     {
         if (view.getId() == R.id.watching_item) //监听的对象是行布局
         {
             Intent intent =  new  Intent(WatchingActivity. this , ContentActivity. class );
             ItemData data = mDataList.get(position -  1 );
             String fromtime = data.from + " "  + Contant.TIME_YEAR + data.time;
             intent.putExtra(Contant.KEY_INTENTER_TITLE, data.title);
             intent.putExtra(Contant.KEY_INTENTER_FROMTIME, fromtime);
             intent.putExtra(Contant.KEY_INTENTER_CONTENT, data.content);
             startActivity(intent);
         }
     }
                                                                  
     //启动异步任务
     private  void  loadTask()
     {
         URL dataUrl =  null ;
         try
         {
             dataUrl =  new  URL(Contant.URL_DATA + mPage + Contant.URL_DATA_FILEFORM);
             // 异步任务下载数据
             LoadDataTask loadDataTask =  new  LoadDataTask();
             loadDataTask.execute(dataUrl);
         }
         catch  (MalformedURLException e)
         {
             e.printStackTrace();
         }
     }
                                                                  
     // 异步任务下载数据
     class  LoadDataTask  extends  AsyncTask<URL, Void, String>
     {
         @Override
         protected  void  onPreExecute()
         {
             loadingview.setVisibility(View.VISIBLE);
         }
         @Override
         protected  String doInURL...  params)
         {
             InputStream is =  null ;
             ByteArrayBuffer strBuf =  new  ByteArrayBuffer( 59658 ); //使用ByteArrayBuffer,直接使用String可能造成读取到的部分内容乱码
             try
             {
                 HttpURLConnection conn = (HttpURLConnection) params[ 0 ].openConnection();
                 conn.setConnectTimeout(Contant.HTTP_TIME_OUT);
                 conn.setReadTimeout(Contant.HTTP_TIME_OUT);
                 // 判断网络连接是否正常
                 if (conn.getResponseCode() != HttpURLConnection.HTTP_OK)
                 {
                     //返回错误提示页面
                     return  null ;
                 }
                                                                              
                 // 下载数据
                 is = conn.getInputStream();
                 byte [] buf =  new  byte [ 1024 ];
                 int  len =  0 ;
                                                                              
                 while  (- 1  != (len = is.read(buf)))
                 {
                     strBuf.append(buf,  0 , len); //直接加入ByteArrayBuffer
                 }
             }
             catch  (IOException e)
             {
                 e.printStackTrace();
             }
             finally
             {
                 if  (is !=  null )
                 {
                     try
                     {
                         is.close();
                     }
                     catch  (IOException e)
                     {
                         e.printStackTrace();
                     }
                 }
             }
             return  new  String(strBuf.buffer()); //bytebuffer数组转成字符串
         }
                                                                      
         // 下载数据解析,更新控件内容
         @Override
         protected  void  onPostExecute(String result)
         {
             loadingview.setVisibility(View.GONE);
                                                                          
             //判断result是否为空
             if (TextUtils.isEmpty(result.trim()))
             {
                 btn_loadmore.setVisibility(View.GONE);
                 errorView.setVisibility(View.VISIBLE);
                 mListView.setVisibility(View.GONE);
                // return;
             }
             else
             {
                 btn_loadmore.setVisibility(View.VISIBLE);
                 btn_footviewloading.setVisibility(View.INVISIBLE);
                 mListView.setVisibility(View.VISIBLE);
                 // 解析json数据
                 ArrayList<ItemData> dataList = parse(result);
                 //更新控件内容
                 setListData(dataList);
                                                                              
             }
         }
     }
                                                                  
    //更新行内容
     private  void  setListData(ArrayList<ItemData> dataList)
     {
         //判断mAdapter是否为空,复用mAdapter实现内容加载,重新set会导致所有内容重新加载(跳到第一行)
         if ( null  == mAdapter)
         {
             createAdapter(dataList); //创建适配器
             mListView.setAdapter(mAdapter);
         }
         else
         {
             mAdapter.notifyDataSetChanged(); //通知listview更新界面
         }
     }
                                                                  
     // 解析json数据
     private  ArrayList<ItemData> parse(String result)
     {
         try
         {
             JSONArray jsonArray =  new  JSONArray(result);
             mPage++; //数据解析完成后,页数修改
             for  ( int  i =  0 ; i < jsonArray.length(); i++)
             {
                 JSONObject jsonObject = jsonArray.getJSONObject(i);
                 String imageUrl = Contant.URL_HOST + jsonObject.getString(Contant.KEY_JSON_IMGURL);
                 String title = jsonObject.getString(Contant.KEY_JSON_TITLE);
                 String from = jsonObject.getString(Contant.KEY_JSON_FROM);
                 String time = jsonObject.getString(Contant.KEY_JSON_TIME);
                 String content = jsonObject.getString(Contant.KEY_JSON_CONTENT);
                 ItemData itemData =  new  ItemData(imageUrl, title, from, time,content);
                 mDataList.add(itemData);
             }
         }
         catch  (JSONException e)
         {
             e.printStackTrace();
         }
         return  mDataList;
     }
                                                                  
     //创建Adapter,设置LiseView
     private  void  createAdapter( final  ArrayList<ItemData> dataList)
     {
         mAdapter =  new  BaseAdapter()
         {
             @Override
             public  View getView( int  position, View convertView,ViewGroup parent)
             {
                 ViewHolder holder;
                 if (convertView ==  null )
                 {
                     LayoutInflater inflater = getLayoutInflater();
                     convertView = inflater.inflate(R.layout.watch_layout,  null );
                     holder =  new  ViewHolder();
                     holder.imageView = (ImageView) convertView.findViewById(R.id.imgView_watch_newspic);
                     holder.textView_title = (TextView) convertView.findViewById(R.id.txtView_watch_title);
                     holder.textView_from = (TextView) convertView.findViewById(R.id.txtView_from);
                     holder.textView_time = (TextView) convertView.findViewById(R.id.txtView_time);
                     holder.progressBar_imageLoading = (ProgressBar) convertView.findViewById(R.id.progressBar_imageloading);
                     convertView.setTag(holder);
                 }
                 else
                 {
                     holder = (ViewHolder) convertView.getTag();
                 }
                                                                              
                 ItemData itemData = dataList.get(position);
                                                                              
                 //启动图片下载任务
                 try
                 {
                     URL url =  new  URL(itemData.imageUrl);
                     if (mCacheMap.containsKey(url))
                     {
                         holder.imageView.setImageBitmap(mCacheMap.get(url));
                     }
                     else
                     {
                         LoadImageTask imageTask =  new  LoadImageTask(holder.imageView,holder.progressBar_imageLoading);
                         imageTask.execute(url);
                     }
                 }
                 catch  (MalformedURLException e)
                 {
                     e.printStackTrace();
                 }
                                                                              
                 holder.textView_title.setText(itemData.title);
                 holder.textView_from.setText(itemData.from);
                 holder.textView_time.setText(itemData.time);
                 return  convertView;
             }
                                                                          
             @Override
             public  long  getItemId( int  position)
             {
                 return  0 ;
             }
                                                                          
             @Override
             public  Object getItem( int  position)
             {
                 return  null ;
             }
                                                                          
             @Override
             public  int  getCount()
             {
                 return  dataList.size();
             }
         };
     }
                                                                  
     //下载图片
     class  LoadImageTask  extends  AsyncTask<URL, Void, Bitmap>
     {
         private  ImageView imageView;
         ProgressBar progressBar_imageLoading;
         public  LoadImageTask(ImageView imageView, ProgressBar progressBar_imageLoading)
         {
             this .imageView = imageView;
             this .progressBar_imageLoading = progressBar_imageLoading;
         }
                                                                      
         @Override
         protected  void  onPreExecute()
         {
             progressBar_imageLoading.setVisibility(View.VISIBLE);
         }
                                                                      
         //下载图片
         @Override
         protected  Bitmap doInURL...  params)
         {
             InputStream is =  null ;
             Bitmap bitmap =  null ;
             try
             {
                 //判断网络连接
                 HttpURLConnection conn = (HttpURLConnection) params[ 0 ].openConnection();
                 conn.setConnectTimeout(Contant.HTTP_TIME_OUT);
                 conn.setReadTimeout(Contant.HTTP_TIME_OUT);
                 if (conn.getResponseCode() != HttpURLConnection.HTTP_OK)
                 {
                     return  null ;
                 }
                                                                              
                 //由url获取bitmap对象
                 is = conn.getInputStream();   //简写方法:is = params[0].openStream()
                 bitmap = BitmapFactory.decodeStream(is);
                 mCacheMap.put(params[ 0 ], bitmap);
             }
             catch  (IOException e)
             {
                 e.printStackTrace();
             }
             finally
             {
                 if ( null  != is )
                 {
                     try
                     {
                         is.close();
                     }
                     catch  (IOException e)
                     {
                         e.printStackTrace();
                     }
                 }
             }
             return  bitmap;
         }
                                                                      
         @Override
         protected  void  onPostExecute(Bitmap bitmap)
         {
             if (bitmap ==  null )
             {
                 //图片加载失败
             }
             else
             {
                 progressBar_imageLoading.setVisibility(View.INVISIBLE);
                 imageView.setImageBitmap(bitmap);
             }
         }
     }
                                                                  
     @Override
     public  boolean  onCreateOptionsMenu(Menu menu)
     {
         getMenuInflater().inflate(R.menu.watching, menu);
         return  true ;
     }
}




其他优化和扩展:

1.图片加载 与设置图片方法一样,将控件对象传到异步任务里

2.惰性加载


其他相关:

1.隐藏headview

1
2
3
4
5
6
7
8
9
<LinearLayout android:id= "@+id/item_root"
     android:layout_width= "fill_parent"
     android:layout_height= "50dip"
     android:orientation= "vertical"  >
  <LinearLayout android:id= "@+id/item_container"
<TextView  android:id= "@+id/tv_1"  />
<TextView  android:id= "@+id/tv_2"  />
  </LinearLayout>
</LinearLayout >

要隐藏的view必须不能是根目录的view的id。







本文转自 glblong 51CTO博客,原文链接:http://blog.51cto.com/glblong/1215407,如需转载请自行联系原作者
目录
相关文章
|
18天前
|
开发框架 前端开发 Android开发
Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势
本文深入探讨了 Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势。这对于实现高效的跨平台移动应用开发具有重要指导意义。
82 4
|
14天前
|
API Android开发 iOS开发
深入探索Android与iOS的多线程编程差异
在移动应用开发领域,多线程编程是提高应用性能和响应性的关键。本文将对比分析Android和iOS两大平台在多线程处理上的不同实现机制,探讨它们各自的优势与局限性,并通过实例展示如何在这两个平台上进行有效的多线程编程。通过深入了解这些差异,开发者可以更好地选择适合自己项目需求的技术和策略,从而优化应用的性能和用户体验。
|
2月前
|
数据采集 JSON 数据处理
抓取和分析JSON数据:使用Python构建数据处理管道
在大数据时代,电商网站如亚马逊、京东等成为数据采集的重要来源。本文介绍如何使用Python结合代理IP、多线程等技术,高效、隐秘地抓取并处理电商网站的JSON数据。通过爬虫代理服务,模拟真实用户行为,提升抓取效率和稳定性。示例代码展示了如何抓取亚马逊商品信息并进行解析。
抓取和分析JSON数据:使用Python构建数据处理管道
|
1月前
|
JSON 数据格式 索引
Python中序列化/反序列化JSON格式的数据
【11月更文挑战第4天】本文介绍了 Python 中使用 `json` 模块进行序列化和反序列化的操作。序列化是指将 Python 对象(如字典、列表)转换为 JSON 字符串,主要使用 `json.dumps` 方法。示例包括基本的字典和列表序列化,以及自定义类的序列化。反序列化则是将 JSON 字符串转换回 Python 对象,使用 `json.loads` 方法。文中还提供了具体的代码示例,展示了如何处理不同类型的 Python 对象。
|
1月前
|
JSON 缓存 前端开发
PHP如何高效地处理JSON数据:从编码到解码
在现代Web开发中,JSON已成为数据交换的标准格式。本文探讨了PHP如何高效处理JSON数据,包括编码和解码的过程。通过简化数据结构、使用优化选项、缓存机制及合理设置解码参数等方法,可以显著提升JSON处理的性能,确保系统快速稳定运行。
|
2月前
|
安全 Android开发 iOS开发
Android vs iOS:探索移动操作系统的设计与功能差异###
【10月更文挑战第20天】 本文深入分析了Android和iOS两个主流移动操作系统在设计哲学、用户体验、技术架构等方面的显著差异。通过对比,揭示了这两种系统各自的独特优势与局限性,并探讨了它们如何塑造了我们的数字生活方式。无论你是开发者还是普通用户,理解这些差异都有助于更好地选择和使用你的移动设备。 ###
52 3
|
2月前
|
调度 Android开发 开发者
构建高效Android应用:探究Kotlin多线程优化策略
【10月更文挑战第11天】本文探讨了如何在Kotlin中实现高效的多线程方案,特别是在Android应用开发中。通过介绍Kotlin协程的基础知识、异步数据加载的实际案例,以及合理使用不同调度器的方法,帮助开发者提升应用性能和用户体验。
59 4
|
28天前
|
JSON API 数据安全/隐私保护
拍立淘按图搜索API接口返回数据的JSON格式示例
拍立淘按图搜索API接口允许用户通过上传图片来搜索相似的商品,该接口返回的通常是一个JSON格式的响应,其中包含了与上传图片相似的商品信息。以下是一个基于淘宝平台的拍立淘按图搜索API接口返回数据的JSON格式示例,同时提供对其关键字段的解释
|
2月前
|
JSON JavaScript Java
在Java中处理JSON数据:Jackson与Gson库比较
本文介绍了JSON数据交换格式及其在Java中的应用,重点探讨了两个强大的JSON处理库——Jackson和Gson。文章详细讲解了Jackson库的核心功能,包括数据绑定、流式API和树模型,并通过示例演示了如何使用Jackson进行JSON解析和生成。最后,作者分享了一些实用的代码片段和使用技巧,帮助读者更好地理解和应用这些工具。
127 0
在Java中处理JSON数据:Jackson与Gson库比较
|
2月前
|
JSON JavaScript API
(API接口系列)商品详情数据封装接口json数据格式分析
在成长的路上,我们都是同行者。这篇关于商品详情API接口的文章,希望能帮助到您。期待与您继续分享更多API接口的知识,请记得关注Anzexi58哦!