Android--多线程之图文混排

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

前言

  本周一直在说Android多线程的那些事儿,本篇博客聊一聊Android开发中一个比较经典的案例,网络数据图文混排,本片博客的案例只涉及关于开启多线程访问网络数据,不涉及缓存的内容。众所周知,从网络上获取一段文本肯定要比获取一张张的图片要省时,所以一般如果是获取图片+文本的数据,会先开启一条线程获取文本数据,再从开启另外的线程来单独获取图片信息。本案例填充一个自定义的XML布局文件作为数据项,并使用ListView承载数据。

 

数据准备

  本案例中的服务端数据以Json的形式传递,在服务端使用.Net开发一个一般处理程序,序列化一个产品对象,里面包含名称、价格、图片名称,最后序列化成JSON格式的数据返回给客户端。关于.Net下如何序列化一个对象成JSON格式,可以参见博客:C#--对象转Json序列化,这里不再累述,大家可以使用自己熟悉的服务端技术模拟JSON数据。

  获取JSON数据的一般处理程序地址:http://192.168.1.102:1231/json/returnCommondityJson.ashx,数据如下

复制代码
1 [{"imageName":"image1.png","name":"苹果","price":12},
2 {"imageName":"image2.png","name":"闹钟","price":56},
3 {"imageName":"image3.png","name":"蛋糕","price":24},
4 {"imageName":"image4.png","name":"零钱包","price":8},
5 {"imageName":"image5.png","name":"书本","price":42},
6 {"imageName":"image6.png","name":"糖果","price":16},
7 {"imageName":"image7.png","name":"西瓜","price":2}]
复制代码

  本案例的URL地址均使用一个CommonUri类进行管理:

复制代码
1 package com.example.handlerimageortext;
2 
3 public class CommonUri {
4     // 访问服务器数据的链接
5     public static final String PRODUCT_URL = "http://192.168.1.102:1231/json/returnCommondityJson.ashx";
6     // 图片的连接
7     public static final String PRODUCT_IMG="http://192.168.1.102:1231/json/img/";
8 }
复制代码

  

使用AsyncTask获取Json数据

  在UI线程中,使用AsyncTask的方式访问网络获取JSON数据,并对其进行解析,关于Android下JSON解析的内容可以参见博客:JSON解析。 

复制代码
 1     public class MyTask extends AsyncTask<String, Void, List<Map<String,Object>>>{
 2         @Override
 3         protected void onPreExecute() {
 4             super.onPreExecute();
 5             // 显示对话框
 6             dialog.show();
 7         }
 8         
 9         @Override
10         protected List<Map<String, Object>> doInBackground(String... params) {
11             List<Map<String,Object>> list=new ArrayList<Map<String,Object>>();
12             try {
13                 // 获取网络JSON格式数据
14                 HttpClient httpClient=new DefaultHttpClient();
15                 HttpPost httpPost=new HttpPost(params[0]);
16                 HttpResponse httpResponse=httpClient.execute(httpPost);
17                 if(httpResponse.getStatusLine().getStatusCode()==200){
18                     String jsonString=EntityUtils.toString(httpResponse.getEntity(),"utf-8");
19                     // 解析Json格式数据,并使用一个List<Map>存放
20                     JSONArray jsonArray=new JSONArray(jsonString);
21                     for(int i=0;i<jsonArray.length();i++){
22                         JSONObject jsonObject=jsonArray.getJSONObject(i);
23                         Map<String,Object> map=new HashMap<String, Object>();
24                         map.put("name",jsonObject.get("name"));
25                         map.put("price",jsonObject.get("price"));
26                         map.put("imageName",jsonObject.get("imageName"));
27                         list.add(map);
28                     }
29                 }
30             } catch (Exception e) {
31                 e.printStackTrace();
32             }
33             return list;
34         }
35         @Override
36         protected void onPostExecute(List<Map<String, Object>> result) {
37             super.onPostExecute(result);
38             // 把查询到的数据传递给适配器
39             adapter.setData(result);
40             // 为ListView设定适配器
41             listview.setAdapter(adapter);
42             adapter.notifyDataSetChanged();
43             // 隐藏对话框
44             dialog.dismiss();
45         }        
46     }
复制代码

 

下载图片信息

  上面的方法中,使用AsyncTask访问网络获取到产品的信息,其中有图片的名称,可以通过这个地址下载图片到本地。

  新创建一个类,用于下载图片,但是需要在主线程中访问图片的信息,可以使用接口回调的方式在Handler中处理子线程发送过来的消息。注释比较全,这里就不再累述了。

复制代码
 1 package com.example.handlerimageortext;
 2 
 3 import java.io.IOException;
 4 import java.net.MalformedURLException;
 5 import java.net.URL;
 6 import android.graphics.drawable.Drawable;
 7 import android.os.Handler;
 8 import android.os.Message;
 9 
10 public class DownLoadImage {
11     private String image_path;
12 
13     public DownLoadImage(String image_path) {
14         // 保存图片的下载地址
15         this.image_path = image_path;
16     }
17 
18     public void loadImage(final ImageCallback callback) {
19         final Handler handler = new Handler() {
20             @Override
21             public void handleMessage(Message msg) {
22                 super.handleMessage(msg);
23                 // 接受到消息后,调用接口回调的方法
24                 callback.getDrawable((Drawable) msg.obj);
25             }
26         };
27         // 开启一个新线程用于访问图片数据
28         new Thread(new Runnable() {
29 
30             @Override
31             public void run() {
32                 try {
33                     // 下载图片为Drawable对象
34                     Drawable drawable = Drawable.createFromStream(new URL(
35                             image_path).openStream(), "");
36                     // 把图片对象包装成一个消息发送给Handler
37                     Message message = Message.obtain();
38                     message.what = 1;
39                     message.obj = drawable;
40                     handler.sendMessage(message);
41                 } catch (MalformedURLException e) {
42                     e.printStackTrace();
43                 } catch (IOException e) {
44                     e.printStackTrace();
45                 }
46             }
47         }).start();
48     }
49     
50     // 定义一个公开的接口,用于执行回调操作
51     public interface ImageCallback {
52         public void getDrawable(Drawable draw);
53     }
54 }
复制代码

 

数据的适配器

  上面已经获取到Json数据中产品的数据,和产品的图片,现在声明一个Adapter类,继承自BaseAdapter,使用一个布局XML资源文件,用于填充数据。

复制代码
 1     public class MyAdapter extends BaseAdapter{
 2         private Context context;
 3         private LayoutInflater layoutInflater;
 4         private List<Map<String,Object>> list=null;
 5         public MyAdapter(Context context){
 6             this.context=context;
 7             layoutInflater=LayoutInflater.from(context);            
 8         }
 9         
10         public void setData(List<Map<String,Object>> list){
11             this.list=list;
12         }
13         
14         @Override
15         public int getCount() {
16             return list.size();
17         }
18 
19         @Override
20         public Object getItem(int position) {
21             return list.get(position);
22         }
23 
24         @Override
25         public long getItemId(int position) {
26             return position;
27         }
28 
29         @Override
30         public View getView(int position, View convertView, ViewGroup parent) {
31             View view=null;
32             if(convertView==null){
33                 // 如果View为空,则以布局XML资源文件填充View
34                 view=layoutInflater.inflate(R.layout.item,null);                
35             }else{
36                 view=convertView;
37             }
38             TextView name=(TextView)view.findViewById(R.id.textView1);
39             TextView price=(TextView)view.findViewById(R.id.textView2);
40             // 因为需要在回调接口中访问这个ImageView控件,所以需要声明为final
41             final ImageView imageview=(ImageView)view.findViewById(R.id.imageView1);
42             name.setText(list.get(position).get("name").toString());
43             price.setText(list.get(position).get("price").toString());
44             
45             // 使用DownLoadImage,下载地址代表的图片
46             DownLoadImage downLoadImage=new DownLoadImage(CommonUri.PRODUCT_IMG+list.get(position).get("imageName").toString());
47             // 使用回调接口,设置ImageView的图片
48             downLoadImage.loadImage(new ImageCallback() {                
49                  @Override
50                 public void getDrawable(Drawable draw) {
51                     imageview.setImageDrawable(draw);
52                 }
53             });
54             return view;
55         }        
56     }
复制代码

  效果展示:


本文转自承香墨影博客园博客,原文链接:http://www.cnblogs.com/plokmju/p/android_ImageOrText.html,如需转载请自行联系原作者


相关文章
|
4月前
|
Java Android开发 UED
🧠Android多线程与异步编程实战!告别卡顿,让应用响应如丝般顺滑!🧵
【7月更文挑战第28天】在Android开发中,确保UI流畅性至关重要。多线程与异步编程技术可将耗时操作移至后台,避免阻塞主线程。我们通常采用`Thread`类、`Handler`与`Looper`、`AsyncTask`及`ExecutorService`等进行多线程编程。
56 2
|
4月前
|
Java Android开发
Android面试题经典之Glide取消加载以及线程池优化
Glide通过生命周期管理在`onStop`时暂停请求,`onDestroy`时取消请求,减少资源浪费。在`EngineJob`和`DecodeJob`中使用`cancel`方法标记任务并中断数据获取。当网络请求被取消时,`HttpUrlFetcher`的`cancel`方法设置标志,之后的数据获取会返回`null`,中断加载流程。Glide还使用定制的线程池,如AnimationExecutor、diskCacheExecutor、sourceExecutor和newUnlimitedSourceExecutor,其中某些禁止网络访问,并根据CPU核心数动态调整线程数。
123 2
|
15天前
|
调度 Android开发 开发者
构建高效Android应用:探究Kotlin多线程优化策略
【10月更文挑战第11天】本文探讨了如何在Kotlin中实现高效的多线程方案,特别是在Android应用开发中。通过介绍Kotlin协程的基础知识、异步数据加载的实际案例,以及合理使用不同调度器的方法,帮助开发者提升应用性能和用户体验。
36 4
|
2月前
|
Java 数据库 Android开发
一个Android App最少有几个线程?实现多线程的方式有哪些?
本文介绍了Android多线程编程的重要性及其实现方法,涵盖了基本概念、常见线程类型(如主线程、工作线程)以及多种多线程实现方式(如`Thread`、`HandlerThread`、`Executors`、Kotlin协程等)。通过合理的多线程管理,可大幅提升应用性能和用户体验。
92 15
一个Android App最少有几个线程?实现多线程的方式有哪些?
|
2月前
|
Java Android开发 UED
🧠Android多线程与异步编程实战!告别卡顿,让应用响应如丝般顺滑!🧵
在Android开发中,为应对复杂应用场景和繁重计算任务,多线程与异步编程成为保证UI流畅性的关键。本文将介绍Android中的多线程基础,包括Thread、Handler、Looper、AsyncTask及ExecutorService等,并通过示例代码展示其实用性。AsyncTask适用于简单后台操作,而ExecutorService则能更好地管理复杂并发任务。合理运用这些技术,可显著提升应用性能和用户体验,避免内存泄漏和线程安全问题,确保UI更新顺畅。
75 5
|
2月前
|
Java 数据库 Android开发
一个Android App最少有几个线程?实现多线程的方式有哪些?
本文介绍了Android应用开发中的多线程编程,涵盖基本概念、常见实现方式及最佳实践。主要内容包括主线程与工作线程的作用、多线程的多种实现方法(如 `Thread`、`HandlerThread`、`Executors` 和 Kotlin 协程),以及如何避免内存泄漏和合理使用线程池。通过有效的多线程管理,可以显著提升应用性能和用户体验。
62 10
|
2月前
|
API Android开发 iOS开发
安卓与iOS开发中的线程管理对比
【9月更文挑战第12天】在移动应用的世界中,安卓和iOS平台各自拥有庞大的用户群体。开发者们在这两个平台上构建应用时,线程管理是他们必须面对的关键挑战之一。本文将深入探讨两大平台在线程管理方面的异同,通过直观的代码示例,揭示它们各自的设计理念和实现方式,帮助读者更好地理解如何在安卓与iOS开发中高效地处理多线程任务。
|
2月前
|
Java Android开发 开发者
安卓应用开发中的线程管理优化技巧
【9月更文挑战第10天】在安卓开发的海洋里,线程管理犹如航行的风帆,掌握好它,能让应用乘风破浪,反之则可能遭遇性能的暗礁。本文将通过浅显易懂的语言和生动的比喻,带你探索如何优雅地处理安卓中的线程问题,从基础的线程创建到高级的线程池运用,让你的应用运行更加流畅。
|
3月前
|
调度 Android开发 开发者
【颠覆传统!】Kotlin协程魔法:解锁Android应用极速体验,带你领略多线程优化的无限魅力!
【8月更文挑战第12天】多线程对现代Android应用至关重要,能显著提升性能与体验。本文探讨Kotlin中的高效多线程实践。首先,理解主线程(UI线程)的角色,避免阻塞它。Kotlin协程作为轻量级线程,简化异步编程。示例展示了如何使用`kotlinx.coroutines`库创建协程,执行后台任务而不影响UI。此外,通过协程与Retrofit结合,实现了网络数据的异步加载,并安全地更新UI。协程不仅提高代码可读性,还能确保程序高效运行,不阻塞主线程,是构建高性能Android应用的关键。
54 4
|
3月前
|
安全 网络安全 数据安全/隐私保护
网络安全与信息安全:关于网络安全漏洞、加密技术、安全意识等方面的知识分享安卓与iOS开发中的线程管理比较
【8月更文挑战第30天】本文将探讨网络安全与信息安全的重要性,并分享关于网络安全漏洞、加密技术和安全意识的知识。我们将了解常见的网络攻击类型和防御策略,以及如何通过加密技术和提高安全意识来保护个人和组织的信息安全。