編輯:Android開發實例
前言
本篇聊一聊Android開發中一個比較經典的案例,網絡數據圖文混排,本文的案例只涉及關於開啟多線程訪問網絡數據,不涉及緩存的內容。眾所周知,從網絡上獲取一段文本肯定要比獲取一張張的圖片要省時,所以一般如果是獲取圖片+文本的數據,會先開啟一條線程獲取文本數據,再從開啟另外的線程來單獨獲取圖片信息。本案例填充一個自定義的XML布局文件作為數據項,並使用ListView承載數據。
數據准備
本案例中的服務端數據以Json的形式傳遞,在服務端使用.Net開發一個一般處理程序,序列化一個產品對象,裡面包含名稱、價格、圖片名稱,最後序列化成JSON格式的數據返回給客戶端。關於.Net下如何序列化一個對象成JSON格式,可以參見:http://www.fengfly.com/plus/view-213375-1.html,這裡不再累述,大家可以使用自己熟悉的服務端技術模擬JSON數據。
獲取JSON數據的一般處理程序地址:http://192.168.1.102:1231/json/returnCommondityJson.ashx,數據如下
- [{"imageName":"image1.png","name":"蘋果","price":12},
- {"imageName":"image2.png","name":"鬧鐘","price":56},
- {"imageName":"image3.png","name":"蛋糕","price":24},
- {"imageName":"image4.png","name":"零錢包","price":8},
- {"imageName":"image5.png","name":"書本","price":42},
- {"imageName":"image6.png","name":"糖果","price":16},
- {"imageName":"image7.png","name":"西瓜","price":2}]
本案例的URL地址均使用一個CommonUri類進行管理:
- package com.example.handlerimageortext;
- public class CommonUri {
- // 訪問服務器數據的鏈接
- public static final String PRODUCT_URL = "http://192.168.1.102:1231/json/returnCommondityJson.ashx";
- // 圖片的連接
- public static final String PRODUCT_IMG="http://192.168.1.102:1231/json/img/";
- }
使用AsyncTask獲取Json數據
在UI線程中,使用AsyncTask的方式訪問網絡獲取JSON數據,並對其進行解析,關於Android下JSON解析的內容可以參見:http://www.fengfly.com/plus/view-213376-1.html。
- public class MyTask extends AsyncTask<String, Void, List<Map<String,Object>>>{
- @Override
- protected void onPreExecute() {
- super.onPreExecute();
- // 顯示對話框
- dialog.show();
- }
- @Override
- protected List<Map<String, Object>> doInBackground(String... params) {
- List<Map<String,Object>> list=new ArrayList<Map<String,Object>>();
- try {
- // 獲取網絡JSON格式數據
- HttpClient httpClient=new DefaultHttpClient();
- HttpPost httpPost=new HttpPost(params[0]);
- HttpResponse httpResponse=httpClient.execute(httpPost);
- if(httpResponse.getStatusLine().getStatusCode()==200){
- String jsonString=EntityUtils.toString(httpResponse.getEntity(),"utf-8");
- // 解析Json格式數據,並使用一個List<Map>存放
- JSONArray jsonArray=new JSONArray(jsonString);
- for(int i=0;i<jsonArray.length();i++){
- JSONObject jsonObject=jsonArray.getJSONObject(i);
- Map<String,Object> map=new HashMap<String, Object>();
- map.put("name",jsonObject.get("name"));
- map.put("price",jsonObject.get("price"));
- map.put("imageName",jsonObject.get("imageName"));
- list.add(map);
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- return list;
- }
- @Override
- protected void onPostExecute(List<Map<String, Object>> result) {
- super.onPostExecute(result);
- // 把查詢到的數據傳遞給適配器
- adapter.setData(result);
- // 為ListView設定適配器
- listview.setAdapter(adapter);
- adapter.notifyDataSetChanged();
- // 隱藏對話框
- dialog.dismiss();
- }
- }
下載圖片信息
上面的方法中,使用AsyncTask訪問網絡獲取到產品的信息,其中有圖片的名稱,可以通過這個地址下載圖片到本地。
新創建一個類,用於下載圖片,但是需要在主線程中訪問圖片的信息,可以使用接口回調的方式在Handler中處理子線程發送過來的消息。注釋比較全,這裡就不再累述了。
- package com.example.handlerimageortext;
- import java.io.IOException;
- import java.net.MalformedURLException;
- import java.net.URL;
- import android.graphics.drawable.Drawable;
- import android.os.Handler;
- import android.os.Message;
- public class DownLoadImage {
- private String image_path;
- public DownLoadImage(String image_path) {
- // 保存圖片的下載地址
- this.image_path = image_path;
- }
- public void loadImage(final ImageCallback callback) {
- final Handler handler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- super.handleMessage(msg);
- // 接受到消息後,調用接口回調的方法
- callback.getDrawable((Drawable) msg.obj);
- }
- };
- // 開啟一個新線程用於訪問圖片數據
- new Thread(new Runnable() {
- @Override
- public void run() {
- try {
- // 下載圖片為Drawable對象
- Drawable drawable = Drawable.createFromStream(new URL(
- image_path).openStream(), "");
- // 把圖片對象包裝成一個消息發送給Handler
- Message message = Message.obtain();
- message.what = 1;
- message.obj = drawable;
- handler.sendMessage(message);
- } catch (MalformedURLException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }).start();
- }
- // 定義一個公開的接口,用於執行回調操作
- public interface ImageCallback {
- public void getDrawable(Drawable draw);
- }
- }
數據的適配器
上面已經獲取到Json數據中產品的數據,和產品的圖片,現在聲明一個Adapter類,繼承自BaseAdapter,使用一個布局XML資源文件,用於填充數據。
- public class MyAdapter extends BaseAdapter{
- private Context context;
- private LayoutInflater layoutInflater;
- private List<Map<String,Object>> list=null;
- public MyAdapter(Context context){
- this.context=context;
- layoutInflater=LayoutInflater.from(context);
- }
- public void setData(List<Map<String,Object>> list){
- this.list=list;
- }
- @Override
- public int getCount() {
- return list.size();
- }
- @Override
- public Object getItem(int position) {
- return list.get(position);
- }
- @Override
- public long getItemId(int position) {
- return position;
- }
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- View view=null;
- if(convertView==null){
- // 如果View為空,則以布局XML資源文件填充View
- view=layoutInflater.inflate(R.layout.item,null);
- }else{
- view=convertView;
- }
- TextView name=(TextView)view.findViewById(R.id.textView1);
- TextView price=(TextView)view.findViewById(R.id.textView2);
- // 因為需要在回調接口中訪問這個ImageView控件,所以需要聲明為final
- final ImageView imageview=(ImageView)view.findViewById(R.id.imageView1);
- name.setText(list.get(position).get("name").toString());
- price.setText(list.get(position).get("price").toString());
- // 使用DownLoadImage,下載地址代表的圖片
- DownLoadImage downLoadImage=new DownLoadImage(CommonUri.PRODUCT_IMG+list.get(position).get("imageName").toString());
- // 使用回調接口,設置ImageView的圖片
- downLoadImage.loadImage(new ImageCallback() {
- @Override
- public void getDrawable(Drawable draw) {
- imageview.setImageDrawable(draw);
- }
- });
- return view;
- }
- }
效果展示:
源碼下載
今天因為要做一個設置開機畫面的功能,主要是讓用戶可以設置自己的開機畫面,應用層需要做讓用戶選擇開機畫面圖片的功能。所以需要做一個簡單的圖片浏覽選擇程序。最後選用G
Android應用程序可以在許多不同地區的許多設備上運行。為了使應用程序更具交互性,應用程序應該處理以適合應用程序將要使用的語言環境方面的文字,數字,文件等。在本章中,我
可以顯示在的Android任務,通過加載進度條的進展。進度條有兩種形狀。加載欄和加載微調(spinner)。在本章中,我們將討論微調(spinner)。Spinner 用
登錄應用程序的屏幕,詢問憑據登錄到一些特定的應用。可能需要登錄到Facebook,微博等本章介紹了,如何創建一個登錄界面,以及如何管理安全問題和錯誤嘗試。首先,必須定義兩