Android--多線程之圖文混排


前言

  本周一直在說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     }

  效果展示:

   源碼下載

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM