隨筆 - 312, 文章 - 14, 評論 - 1393, 引用 - 0
          數據加載中……

          《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
          主站蜘蛛池模板: 北京市| 沈阳市| 且末县| 长宁区| 邮箱| 柳河县| 商河县| 雅安市| 河北省| 出国| 亳州市| 信丰县| 舟山市| 丰顺县| 青川县| 汉川市| 襄樊市| 河东区| 紫阳县| 岳阳县| 宣武区| 琼海市| 灵丘县| 惠东县| 历史| 荆门市| 镇原县| 炎陵县| 临潭县| 全南县| 梁平县| 丰台区| 上犹县| 安乡县| 浪卡子县| 沁水县| 张北县| 安泽县| 六安市| 光泽县| 友谊县|