資料準備
本案例中的服務端資料以Json的形式傳遞,在服務端使用.Net開發一個一般處理常式,序列化一個產品對象,裡麵包含名稱、價格、圖片名稱,最後序列化成JSON格式的資料返回給用戶端。
資料如下
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資料,並對其進行解析
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 @Override10 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 @Override36 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 @Override21 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 @Override31 public void run() {32 try {33 // 下載圖片為Drawable對象34 Drawable drawable = Drawable.createFromStream(new URL(35 image_path).openStream(), "");36 // 把圖片對象封裝成一個訊息發送給Handler37 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 @Override15 public int getCount() {16 return list.size();17 }18 19 @Override20 public Object getItem(int position) {21 return list.get(position);22 }23 24 @Override25 public long getItemId(int position) {26 return position;27 }28 29 @Override30 public View getView(int position, View convertView, ViewGroup parent) {31 View view=null;32 if(convertView==null){33 // 如果View為空白,則以布局XML資源檔填充View34 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控制項,所以需要聲明為final41 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 @Override50 public void getDrawable(Drawable draw) {51 imageview.setImageDrawable(draw);52 }53 });54 return view;55 } 56 }
效果展示: