隨筆 - 312, 文章 - 14, 評論 - 1393, 引用 - 0

          導航

          <2010年9月>
          2930311234
          567891011
          12131415161718
          19202122232425
          262728293012
          3456789

          公告

          關注我的新浪微博

          我的著作









          常用鏈接

          留言簿(126)

          我參與的團隊

          隨筆分類(818)

          隨筆檔案(310)

          文章分類(1)

          文章檔案(8)

          相冊

          ADSL、3G查詢

          CSDN

          eclipse

          ibm

          Java EE

          Linux

          Web

          云服務

          代理網站

          關注的網站

          協議

          喜歡的Blog

          國內廣告平臺

          圖書出版

          在線培訓

          開發工具

          微博客戶端

          手機鈴聲

          操作系統

          • ReactOS
          • 一個與windowXP/2003兼容的操作系統

          數學

          文件格式

          源碼資源

          移動(Mobile)

          編程語言

          英語學習

          最新隨筆

          搜索

          •  

          積分與排名

          • 積分 - 1974562
          • 排名 - 6

          最新評論

          閱讀排行榜

          評論排行榜

          《Android/OPhone開發完全講義》連載(7):使用SharedPreferences存取復雜數據

          本文為《Android/OPhone開發完全講義》一書的內容連載。轉載請注明出處

              我們知道SharedPreferences只能保存簡單類型的數據,例如,String、int等。如果想用SharedPreferences存取更 復雜的數據類型(類、圖像等),就需要對這些數據進行編碼。我們通常會將復雜類型的數據轉換成Base64編碼,然后將轉換后的數據以字符串的形式保存在 XML文件中。

          Android SDK中并未提供Base64編碼和解碼庫。因此,需要使用第三方的jar包。在本例中使用了Apache Commons組件集中的Codec組件進行Base64編碼和解碼。讀者可以從如下的地址下載Codec組件的安裝包。

          http://commons.apache.org/codec/download_codec.cgi

              在Android工程目錄的lib子目錄中已經包含了Codec組件的jar包(commons-codec-1.4.jar),因此,讀者可以在該工程中直接使用Codec組件。

              在本例中將一個Product類的對象實例和一個圖像保存在XML文件中,并在程序重新運行后從XML文件裝載Product對象和圖像。下面是Product類的代碼:

          package net.blogjava.mobile;
          import java.io.Serializable;
          // 需要序列化的類必須實現Serializable接口
          public class Product implements Serializable
          {
          private String id;
          private String name;
          private float price;
          // 此處省略了屬性的getter和setter方法
           

          在存取數據之前,需要使用下面的代碼創建一個SharedPreferences對象。

          mySharedPreferences = getSharedPreferences("base64",Activity.MODE_PRIVATE);

          其中mySharedPreferences是在類中定義的SharedPreferences類型變量。

          在保存Product對象之前,需要創建Product對象,并將相應組件中的值賦給Product類的相應屬性。將Product對象保存在XML文件中的代碼如下:

          Product product = new Product();
          product.setId(etProductID.getText().toString());
          product.setName(etProductName.getText().toString());
          product.setPrice(Float.parseFloat(etProductPrice.getText().toString()));
          ByteArrayOutputStream baos 
          = new ByteArrayOutputStream();
          ObjectOutputStream oos 
          = new ObjectOutputStream(baos);
          // 將Product對象放到OutputStream中
          oos.writeObject(product);
          mySharedPreferences 
          = getSharedPreferences("base64", Activity.MODE_PRIVATE);
          // 將Product對象轉換成byte數組,并將其進行base64編碼
          String productBase64 = new String(Base64.encodeBase64(baos.toByteArray()));
          SharedPreferences.Editor editor 
          = mySharedPreferences.edit();
          // 將編碼后的字符串寫到base64.xml文件中
          editor.putString("product", productBase64);
          editor.commit();

          保存圖像的方法與保存Product對象的方法類似。由于在保存之前,需要選擇一個圖像,并將該圖像顯示在ImageView組件中,因此,從ImageView組件中可以直接獲得要保存的圖像。將圖象保存在XML文件中的代碼如下:

          ByteArrayOutputStream baos = new ByteArrayOutputStream();
          // 將ImageView組件中的圖像壓縮成JPEG格式,并將壓縮結果保存在ByteArrayOutputStream對象中
          ((BitmapDrawable) imageView.getDrawable()).getBitmap().compress(CompressFormat.JPEG, 50, baos);
          String imageBase64 
          = new String(Base64.encodeBase64(baos.toByteArray()));
          // 保存由圖像字節流轉換成的Base64格式字符串
          editor.putString("productImage", imageBase64);
          editor.commit();

              其中compress方法的第2個參數表示壓縮質量,取值范圍是0至100,0表示最高壓縮比,但圖像效果最差,100則恰恰相反。在本例中取了一個中間值50。

              從XML文件中裝載Product對象和圖像是保存的逆過程。也就是從XML文件中讀取Base64格式的字符串,然后將其解碼成字節數組,最后將字節數組轉換成Product和Drawable對象。裝載Product對象的代碼如下:

          String productBase64 = mySharedPreferences.getString("product""");
          // 對Base64格式的字符串進行解碼
          byte[] base64Bytes = Base64.decodeBase64(productBase64.getBytes());
          ByteArrayInputStream bais 
          = new ByteArrayInputStream(base64Bytes);
          ObjectInputStream ois 
          = new ObjectInputStream(bais);
          // 從ObjectInputStream中讀取Product對象
          Product product = (Product) ois.readObject();

          裝載圖像的代碼如下:
          String imageBase64 = mySharedPreferences.getString("productImage","");
          base64Bytes 
          = Base64.decodeBase64(imageBase64.getBytes());
          bais 
          = new ByteArrayInputStream(base64Bytes);
          // 在ImageView組件上顯示圖像
          imageView.setImageDrawable(Drawable.createFromStream(bais,"product_image"));

          在上面的代碼中使用了Drawable類的createFromStream方法直接從流創建了Drawable對象,并使用setImageDrawable方法將圖像顯示在ImageView組件上。

          在 這里需要提一下的是圖像選擇。在本例中使用了res\drawable目錄中的除了icon.png外的其他圖像。為了能列出這些圖像,本例使用了 Java的反射技術來枚舉這些圖像的資源ID。基本原理是枚舉R.drawable類中所有的Field,并獲得這些Field的值。如果采用這個方法, 再向drawable目錄中添加新的圖像,或刪除以前的圖像,并不需要修改代碼,程序就可以顯示最新的圖像列表。枚舉圖像資源ID的代碼如下:
          // 獲得R.drawable類中所有的Field
          Field[] fields = R.drawable.class.getDeclaredFields();
          for (Field field : fields)
          {
          if (!"icon".equals(field.getName()))
          imageResIdList.add(field.getInt(R.drawable.
          class));
          }

              運行本例后,單擊【選擇產品圖像】按鈕,會顯示一個圖像選擇對話框,如圖1所示。選中一個圖像后,關閉圖像選擇對話框,并單擊【保存】按鈕。如果保存成功,將顯示如圖2所示的提示對話框。當再次運行程序后,會顯示上次成功保存的數據。





          查看base64.xml文件,會看到如下的內容:

          <?xml version='1.0' encoding='utf-8' standalone='yes' ?>
          <map>
          <string name="productImage">/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDABDsyj7yK3</string>
          <string name="product">rO0ABXNyABtuZXQuYmxvZ2phdmEubW9iaWxlLlByb2</string>
          </map>

              注意:雖然可以采用編碼的方式通過SharedPreferences保存任何類型的數據,但作者并不建議使用SharedPreferences保存尺寸很大的數據。如果讀者要存取更




          Android開發完全講義(第2版)(本書版權已輸出到臺灣)

          http://product.dangdang.com/product.aspx?product_id=22741502



          Android高薪之路:Android程序員面試寶典 http://book.360buy.com/10970314.html


          新浪微博:http://t.sina.com.cn/androidguy   昵稱:李寧_Lining

          posted on 2010-09-08 09:49 銀河使者 閱讀(4068) 評論(5)  編輯  收藏 所屬分類: java 原創移動(mobile) 圖書Android/OPhone

          評論

          # re: 《Android/OPhone開發完全講義》連載(7):使用SharedPreferences存取復雜數據[未登錄]  回復  更多評論   

          PreferenceScreenExt 代碼:




          package asai.cn.seekbardemo;

          import java.util.ArrayList;
          import java.util.HashMap;
          import java.util.List;

          import android.app.Dialog;
          import android.content.Context;
          import android.content.DialogInterface;
          import android.content.SharedPreferences;
          import android.preference.Preference;
          import android.preference.PreferenceGroup;
          import android.util.AttributeSet;
          import android.view.LayoutInflater;
          import android.view.View;
          import android.view.ViewGroup;
          import android.view.View.OnClickListener;
          import android.widget.AdapterView;
          import android.widget.ListView;
          import android.widget.RelativeLayout;
          import android.widget.SimpleAdapter;
          import android.widget.TextView;
          import android.widget.AdapterView.OnItemClickListener;

          public class PreferenceScreenExt extends PreferenceGroup implements
          OnItemClickListener, DialogInterface.OnDismissListener {

          private Dialog dialog;
          private TextView title, summary;
          private SharedPreferences share;
          private RelativeLayout area;
          private ListView listView;
          List<Preference> list;

          private List<HashMap<String, String>> listStr;
          private CharSequence[] mEntries;
          private String mValue;

          public PreferenceScreenExt(Context context, AttributeSet attrs) {
          this(context, attrs, android.R.attr.preferenceScreenStyle);
          // TODO Auto-generated constructor stub
          }

          public PreferenceScreenExt(Context context, AttributeSet attrs, int defStyle) {
          super(context, attrs, android.R.attr.preferenceScreenStyle);
          // TODO Auto-generated constructor stub
          int resouceId = attrs.getAttributeResourceValue(null, "Entries", 0);
          if (resouceId > 0) {
          mEntries = getContext().getResources().getTextArray(resouceId);
          }
          }

          @Override
          protected View onCreateView(ViewGroup parent) {
          // TODO Auto-generated method stu
          View view = LayoutInflater.from(getContext()).inflate(
          R.layout.preference_screen, null);
          area = (RelativeLayout) view.findViewById(R.id.area);
          share = getPreferenceManager().getSharedPreferences();
          title = (TextView) view.findViewById(R.id.title);
          summary = (TextView) view.findViewById(R.id.summary);
          title.setText(getTitle());
          summary.setText(share.getString(getKey(), getSummary() == null ? ""
          : getSummary().toString()));
          area.setOnClickListener(new OnClickListener() {

          @Override
          public void onClick(View v) {
          // TODO Auto-generated method stub
          showDialog();
          }
          });
          return view;
          }

          public void bindView(ListView listview) {
          int length = mEntries.length;
          int i = 0;
          listStr = new ArrayList<HashMap<String, String>>();
          for (i = 0; i < length; i++) {
          HashMap<String, String> map = new HashMap<String, String>();
          map.put("keyname", mEntries[i].toString());
          listStr.add(map);
          }
          SimpleAdapter simple = new SimpleAdapter(getContext(), listStr,
          R.layout.dialog_view, new String[] { "keyname" },
          new int[] { R.id.text });
          listview.setAdapter(simple);
          listview.setOnItemClickListener(this);
          }

          public void showDialog() {
          listView = new ListView(getContext());
          bindView(listView);
          dialog = new Dialog(getContext(), android.R.style.Theme_NoTitleBar);
          dialog.setContentView(listView);
          dialog.setOnDismissListener(this);
          dialog.show();
          }

          @Override
          public void onItemClick(AdapterView<?> parent, View view, int position,
          long id) {
          // TODO Auto-generated method stub
          mValue = listStr.get(position).get("keyname").toString();
          SharedPreferences.Editor editor = getEditor();
          editor.putString(getKey(), mValue);
          editor.commit();
          dialog.dismiss();
          }

          @Override
          public void onDismiss(DialogInterface dialog) {
          // TODO Auto-generated method stub
          summary.setText(mValue);
          }
          }
          2010-09-25 14:35 | terry

          # re: 《Android/OPhone開發完全講義》連載(7):使用SharedPreferences存取復雜數據[未登錄]  回復  更多評論   

          對應的XML


          preference_screen.xml

          <RelativeLayout android:id="@+id/area" android:gravity="center_vertical"
          android:layout_marginTop="5px" android:clickable="true"
          xmlns:android="http://schemas.android.com/apk/res/android"
          android:background="@drawable/row_bg" android:layout_width="fill_parent"
          android:layout_height="wrap_content">

          <TextView android:id="@+id/title" android:layout_marginLeft="20dp"
          android:textAppearance="?android:attr/textAppearanceLarge"
          android:textSize="35sp" android:layout_width="wrap_content"
          android:layout_height="wrap_content">
          </TextView>
          <TextView android:id="@+id/summary"
          android:layout_marginRight="20dp" android:textSize="35sp"
          android:textAppearance="?android:attr/textAppearanceLarge"
          android:layout_alignParentRight="true" android:layout_width="wrap_content"
          android:layout_height="wrap_content">
          </TextView>
          </RelativeLayout>
          2010-09-25 14:35 | terry

          # re: 《Android/OPhone開發完全講義》連載(7):使用SharedPreferences存取復雜數據[未登錄]  回復  更多評論   

          dialog_view.xml


          <LinearLayout android:layout_width="fill_parent"
          android:background="@drawable/row_bg" xmlns:android="http://schemas.android.com/apk/res/android"
          android:orientation="vertical" android:gravity="center"
          android:layout_height="fill_parent">


          <TextView android:id="@+id/text" android:layout_marginLeft="20dp"
          android:textAppearance="?android:attr/textAppearanceLarge"
          android:textSize="35sp" android:layout_width="wrap_content"
          android:layout_height="wrap_content">
          </TextView>


          </LinearLayout>
          2010-09-25 14:36 | terry

          # re: 《Android/OPhone開發完全講義》連載(7):使用SharedPreferences存取復雜數據[未登錄]  回復  更多評論   

          隨便測試的ActivityGroup:


          package asai.cn.seekbardemo;

          import android.app.ActivityGroup;
          import android.app.LocalActivityManager;
          import android.content.Intent;
          import android.os.Bundle;
          import android.view.View;
          import android.view.Window;
          import android.view.View.OnClickListener;
          import android.widget.Button;
          import android.widget.LinearLayout;

          public class main extends ActivityGroup implements OnClickListener {

          private LocalActivityManager lm;
          private LinearLayout layout;
          private Button btn, btn2;

          @Override
          protected void onCreate(Bundle savedInstanceState) {
          // TODO Auto-generated method stub
          super.onCreate(savedInstanceState);
          setContentView(R.layout.group);
          lm = getLocalActivityManager();

          layout = (LinearLayout) findViewById(R.id.layout);
          btn = (Button) findViewById(R.id.Button01);
          btn2 = (Button) findViewById(R.id.Button02);

          btn.setOnClickListener(this);
          btn2.setOnClickListener(this);
          Intent intent = new Intent(this, seekBarDemo.class);
          intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
          Window w = lm.startActivity("test", intent);
          View v = w.getDecorView();
          layout.removeAllViews();
          layout.addView(v);
          layout.invalidate();

          }

          @Override
          public void onClick(View v) {
          // TODO Auto-generated method stub
          switch (v.getId()) {
          case R.id.Button01:
          Intent intent = new Intent(this, seekBarDemo.class);
          intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
          Window w = lm.startActivity("test", intent);
          View view = w.getDecorView();
          layout.removeAllViews();
          layout.addView(view);
          break;
          case R.id.Button02:
          Intent in = new Intent(this, test.class);
          in.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
          Window win = lm.startActivity("ww", in);
          View vw = win.getDecorView();
          layout.removeAllViews();
          layout.addView(vw);
          break;
          default:
          break;
          }
          }
          }
          2010-09-25 14:37 | terry

          # re: 《Android/OPhone開發完全講義》連載(7):使用SharedPreferences存取復雜數據[未登錄]  回復  更多評論   

          還少了個XML配置:
          <asai.cn.seekbardemo.PreferenceScreenExt
          Entries="@array/country" android:title="收音區域" android:summary="美國"
          android:key="eeg">
          </asai.cn.seekbardemo.PreferenceScreenExt>


          數組:
          <string-array name="country">
          <item>美國</item>
          <item>中國</item>
          <item>英國</item>
          </string-array>
          2010-09-25 14:42 | terry
          主站蜘蛛池模板: 南通市| 浦县| 纳雍县| 南京市| 登封市| 交城县| 常熟市| 全州县| 南丹县| 普兰店市| 白水县| 牡丹江市| 民县| 巴塘县| 永善县| 龙里县| 瓮安县| 肇庆市| 兴文县| 随州市| 奉新县| 根河市| 改则县| 衡山县| 九台市| 曲靖市| 高淳县| 叶城县| 宜都市| 白河县| 会昌县| 襄汾县| 衡阳市| 墨竹工卡县| 包头市| 谷城县| 吉隆县| 乐东| 巨鹿县| 南陵县| 兴化市|