posts - 78, comments - 34, trackbacks - 0, articles - 1
            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

                 今日重點內容是Adnroid的數據存儲和訪問。Android的數據存儲有五種:文件

          SharedPreferences、SQLite數據庫、內容提供者(Content provider)、網絡。今天老黎講解Android的單元測試、文件存儲和訪問以及解析XML文件。

           

          一、Android的單元測試

                 昨天進行的只是簡單的開發,但從今天起的開發內容比較重要。所以首先應該學習Android的單元測試。在Android工程中添加單元測試的方法:

                 1.向androidManifest.xml加入:

                 <uses-library android:name="android.test.runner" />,它必須位于<application>元素體內。<application>的子元素。

                  <instrumentation android:name="android.test.InstrumentationTestRunner"

            android:targetPackage="cn.itcast.action" android:label="Tests for My App" />

                 </application> <application>元素并列<application>元素的兄弟元素。這里的targetPackage必須是我們創建工程時指定的包名。

           

                 2.單元測試類

                 我們的單元測試類,必須繼承自AndroidTestCase類。

           

                 3.單元測試方法

                 單元測試方法必須以test開頭

           

                 4.方法拋出異常

                 方法要throws Throwable異常,ThrowableException的父類,單元測試框架捕獲Throwable

           

                 5.調用測試

                 outline面板或方法名上右鍵,Run AS Android Junit Test

           

                 6.打印信息

                 android中不能使用System.out.println()打印信息,但我們可以使用Android為我們提供的Log類來打印信息。可以使用Log.i打開info信息、使用Log.e打印error信息、使用Log.d打印調試信息...

           

                 7.查看打印的信息

                 因為我們安裝了ADT插件,所以選擇菜單windows->Show View->Other...->Android->LogCat,打開 LogCat面板。在這個面板中我們可以看到Android輸出的所有信息。

           

                 但我們只想查看我們自己輸出的信息怎么辦呢?面板的右上角有個+號,使用它可以創建一個過濾器。比如我們輸入一個info信息調用Log.i(tag,”Hello Android!”),tag是信息的標簽,一般使用類名。創建過濾器,將Filter Name和by Log Tag都設置為我的們的tag ,OK。它為我們創建了一個新的以tag名稱的分頁,在這個分頁中我們可以查看過濾出來的信息。

           

                 LogCat面板中還有VDIWE五個選擇按鈕,從右向左依次包含。比如我們選擇D,那么下面的面板將只顯示DIW這三類信息。

           

          二、Android的文件存儲和訪問

                 Android的文件讀寫與JavaSE的文件讀寫相同,都是使用IO流。而且Android使用的正是JavaSEIO流,下面我們通過一個練習來學習Android的文件讀寫。

           

                 1.創建一個Android工程

                 Project name:FileRW

                 BuildTarget:Android2.1

                 Application name:文件讀寫

                 Package name:com.changcheng.File

                 Create Activity:FileRW

                 Min SDK Version:7

           

                 2.編輯strings.xml文件內容:

          <?xml version="1.0" encoding="utf-8"?>

          <resources>

              <string name="hello">Hello World, FileRW!</string>

              <string name="app_name">文件讀寫</string>

              <string name="file_name">文件名</string>

              <string name="file_content">文件內容</string>

              <string name="button_file_save">保存</string>

              <string name="button_file_read">讀取</string>

              <string name="file_save_success">保存文件成功</string>

              <string name="file_save_failed">保存文件失敗</string>

              <string name="file_read_failed">讀取文件失敗</string>

          </resources>

           

                 3.編輯main.xml文件內容:

          <?xml version="1.0" encoding="utf-8"?>

          <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

                 android:orientation="vertical" android:layout_width="fill_parent"

                 android:layout_height="fill_parent">

                 <!-- 文件名 -->

                 <TextView android:layout_width="fill_parent"

                        android:layout_height="wrap_content" android:text="@string/file_name" />

                 <EditText android:layout_width="fill_parent"

                        android:layout_height="wrap_content" android:id="@+id/et_file_name" />

                 <!-- 文件內容 -->

                 <TextView android:layout_width="fill_parent"

                        android:layout_height="wrap_content" android:text="@string/file_content" />

                 <EditText android:layout_width="fill_parent"

                        android:layout_height="wrap_content" android:minLines="3"

                        android:id="@+id/et_file_content" />

                 <!-- 保存和讀取按鈕,采用相對布局 -->

                 <RelativeLayout android:layout_width="fill_parent"

                        android:layout_height="wrap_content">

                        <!-- 保存按鈕 -->

                        <Button android:layout_width="wrap_content"

                               android:layout_height="wrap_content" android:text="@string/button_file_save"

                               android:id="@+id/bt_save" />

                        <!-- 讀取按鈕 -->

                        <Button android:layout_width="wrap_content"

                               android:layout_height="wrap_content" android:layout_toRightOf="@id/bt_save"

                               android:text="@string/button_file_read" android:id="@+id/bt_read" />

                 </RelativeLayout>

          </LinearLayout>

           

                 4.添加java代碼

                 Android建議采用MVC開發模式,所以我們在Android應用開發中最好使用MVC設計模式。MVC設計模式使三層分離,從而很好的解耦,何樂而不為。

                 首先我們向工程中添加一個FileService.java

          package com.changcheng.file.service;

           

          import java.io.ByteArrayOutputStream;

          import java.io.FileInputStream;

          import java.io.FileOutputStream;

          import android.content.Context;

           

          public class FileService {

           

                 Context context;

           

                 public FileService(Context context) {

                        this.context = context;

                 }

           

                 /**

                  * 保存文件

                  *

                  * @param fileName

                  * @param fileContent

                  * @throws Exception

                  */

                 public void save(String fileName, String fileContent) throws Exception {

                        // Activity的父類的父類就是contextcontext與其他框架中的context相同為我們以供了一些核心操作工具。

                        FileOutputStream fileOutputStream = this.context.openFileOutput(

                                      fileName, Context.MODE_PRIVATE);

                        fileOutputStream.write(fileContent.getBytes());

                 }

           

                 /**

                  * 讀取文件

                  *

                  * @param fileName

                  * @return

                  * @throws Exception

                  */

                 public String read(String fileName) throws Exception {

                        FileInputStream fileInputStream = this.context.openFileInput(fileName);

                        ByteArrayOutputStream byteArray = new ByteArrayOutputStream();

           

                        byte[] buffer = new byte[1024];

                        int len = 0;

                        while ((len = fileInputStream.read(buffer)) > 0) {

                               byteArray.write(buffer, 0, len);

                        };

                        return byteArray.toString();

                 }

          }

                 文件讀寫的操作模式:

                 Context.MODE_PRIVATE:新內容覆蓋原內容

                 Context.MODE_APPEND:新內容追加到原內容后

                 Context.MODE_WORLD_READABLE:允許其他應用程序讀取

                 Context.MODE_WORLD_WRITEABLE:允許其他應用程序寫入,會覆蓋原數據。

                 可以使用+連接這些權限。

           

                 然后再向工程中添加FileButtonOnClickEvent.java

          package com.changcheng.file.event;

           

          import com.changcheng.file.R;

          import com.changcheng.file.service.FileService;

          import android.app.Activity;

          import android.util.Log;

          import android.view.View;

          import android.view.View.OnClickListener;

          import android.widget.Button;

          import android.widget.EditText;

          import android.widget.Toast;

           

          /**

           * 按鈕事件類

           * @author Administrator

           * 

           */

          public class FileButtonOnClickEvent implements OnClickListener {

                

                 // 通過activity獲取其他控件

                 private Activity activity;

                 // 通過FileService讀寫文件

                 private FileService fileService;

                 // 打印信息用的標簽

                 private static final String TAG = "FileButtonOnClickEvent";

           

                 public FileButtonOnClickEvent(Activity activity) {

                        this.fileService = new FileService(activity);

                        this.activity = activity;

                 }

           

                 @Override

                 public void onClick(View v) {

                        Button button = (Button) v;

                        switch (button.getId()) {

                        case R.id.bt_save:

                               // 獲取文件名

                               EditText etFileNameS = (EditText) this.activity

                                             .findViewById(R.id.et_file_name);

                               String fileNameS = etFileNameS.getText().toString();

                               // 獲取文件內容

                               EditText etFileConS = (EditText) this.activity

                                             .findViewById(R.id.et_file_content);

                               String fileContentS = etFileConS.getText().toString();

                               // 保存

                               try {

                                      this.fileService.save(fileNameS, fileContentS);

                                      // 在窗口中顯示一個特效信息框

                                      Toast.makeText(this.activity, R.string.file_save_success,

                                                    Toast.LENGTH_LONG).show();

                                      Log.i(TAG, "save file success!");

                               } catch (Exception e) {

                                      Toast.makeText(this.activity, R.string.file_save_failed,

                                                    Toast.LENGTH_LONG).show();

                                      Log.e(TAG, e.toString());

                               }

                               break;

                        case R.id.bt_read:

                               // 獲取文件名

                               EditText etFileNameR = (EditText) this.activity

                                             .findViewById(R.id.et_file_name);

                               String fileNameR = etFileNameR.getText().toString();

                               // 讀取文件

                               try {

                                      String fielContentR = this.fileService.read(fileNameR);

                                      EditText etFileConR = (EditText) this.activity

                                                    .findViewById(R.id.et_file_content);

                                      etFileConR.setText(fielContentR);

                                      Log.i(TAG, "read file success!");

                               } catch (Exception e) {

                                      Toast.makeText(this.activity, R.string.file_read_failed,

                                                    Toast.LENGTH_LONG).show();

                                      Log.e(TAG, e.toString());

                               }

                               break;

                        default:

                               break;

                        }

                 }

          }

           

                 最后編輯FileRW.java

          package com.changcheng.file;

           

          import com.changcheng.file.event.FileButtonOnClickEvent;

          import android.app.Activity;

          import android.os.Bundle;

          import android.widget.Button;

           

          public class FileRW extends Activity {

                 /** Called when the activity is first created. */

                 @Override

                 public void onCreate(Bundle savedInstanceState) {

                        super.onCreate(savedInstanceState);

                        setContentView(R.layout.main);

                        // 獲取所有按鈕

                        Button buttonRead = (Button) this.findViewById(R.id.bt_read);

                        Button buttonSave = (Button) this.findViewById(R.id.bt_save);

                        // 為按鈕添加事件

                        FileButtonOnClickEvent fileBtOnClickEve = new FileButtonOnClickEvent(this);

                        buttonRead.setOnClickListener(fileBtOnClickEve);

                        buttonSave.setOnClickListener(fileBtOnClickEve);

                 }

          }

                 我們的FileRW.java的可讀性是否很好?當然!以后繼續改進。但我們的FileService并未使用接口,在JavaEE都使用接口來開發,這樣可以實現解耦。由于在Android是手機操作系統平臺,如果我們開設的類比較多,會占用系統資源,從而導致系統變慢。所以,盡量的減少接口或類的定義,但也要盡量的做到程序的可讀性要好。

           

                 在這里我就不演示使用Android的單元測試了,因為它十分容易。我們可以定義一個單元測試類專門用于測試FileService類,Android的測試單元將自動啟動模擬器。

           

                 5.運行程序

                 啟動模擬器,部署我們的程序。輸入文件名和文件內容,點擊保存。文件被保存在Android的什么位置?我們知道Android是基于Linux實現的。所以它的根目錄是”/”,我們的文件被保存在”/data/data/com.changcheng.file/files”目錄下。

           

                 我們也可以通過菜單Windows->Show View->Other...->Android->File Explorer,打開 File Explorer面板。通過它可以查看Android的目錄結構:

                 data:應用數據,我們保存的文件在/data/data/packagename/files。

                 sdcard:現在的手機一般都可以外插一個SD卡,這個目錄就是SDCard的目錄。操作此目錄時需要在主配置文件中注冊操作權限。

                 systemAndroid操作系統的文件,我們不要修改。

                 我們可以點擊 File Explorer右上角的軟盤向左箭頭圖標,導出文件。

           

                 6.其他程序獲取文件路徑的方法

                 1.絕對路徑:/data/data/packagename/files/filename;

                 2.context:context.getFilesDir()+”/filename”;

                 緩存目錄:/data/data/packagename/CachegetCacheDir();

                 如果文件過大就不能存放在手機的文件目錄,需要存儲到SDCard上。

                 SDCard目錄:/sdcard/Environment.getExternalStorageDirectory()

                 使用SDCard目錄前,需要判斷是否有sdcardEnvironment.getExternalStorageState()。操作此目錄時需要在主配置文件中注冊操作權限。

           

          三、Android的解析XML文件

                 我們在學習JavaWEB基礎時,老方有講解使用JavaSE解析XML文件。我們在學習JavaEE時一般都使用dom4j解析XML文件。在Android中解析XMLJavaSEJavaEE都差不多,我們也可以在Andorid中使用dom4j,但這會占用系統的資源。

           

                 Andorid中解析XML有三種技術SAXDOMpull,重點是Saxpull。尤其是pullAndroid推薦使用,Android系統自身就是使用pull來解析的。pull的解析速度和資源的占用可以與sax相媲美,但使用上比sax更簡單。

           

                 1.Sax解析XML

                 Sax是采用事件驅動的方式解析XML文件的,它是流式處理的。什么是流式的?就是從文檔首開始流向文檔尾,不可倒退。

                

                 我們需要編輯一個繼承自DefaultHandler的類,因為DefaultHandler實現了ContentHandler接口。關于使用Sax解析XML文件的方式和代碼,在此就不做總結了。

                

                 2.DOM解析XML

                 DOM解析XML在我之前的日志中有介紹,在此就不再總結了。

           

                 明天繼續學習pull解析XML文件!

           


          評論

          # re: 2010-02-27 傳智播客—Android(二)數據存儲和訪問 之文件 [未登錄]  回復  更多評論   

          2010-03-11 11:01 by lveyo
          FileOutputStream fileOutputStream = this.context.openFileOutput(
          fileName, Context.MODE_PRIVATE);
          fileOutputStream.write(fileContent.getBytes());

          這個fileOutputStream使用完以后不用關閉(fileOutputStream.close())嗎?

          # re: 2010-02-27 傳智播客—Android(二)數據存儲和訪問 之文件 [未登錄]  回復  更多評論   

          2010-03-11 11:03 by lveyo
          FileOutputStream fileOutputStream = this.context.openFileOutput(
          fileName, Context.MODE_PRIVATE);
          fileOutputStream.write(fileContent.getBytes());

          這個fileOutputStream用完之后不用調用close()方法把流資源釋放嗎?

          # re: 2010-02-27 傳智播客—Android(二)數據存儲和訪問 之文件   回復  更多評論   

          2010-03-11 22:39 by 長城
          @lveyo

          不好意思,這個需要關閉!

          # re: 2010-02-27 傳智播客—Android(二)數據存儲和訪問 之文件   回復  更多評論   

          2012-10-17 20:34 by 鍋煽豆腐
          韓國

          只有注冊用戶登錄后才能發表評論。


          網站導航:
          博客園   IT新聞   Chat2DB   C++博客   博問  
           
          主站蜘蛛池模板: 克东县| 佳木斯市| 和顺县| 彰化县| 定结县| 布拖县| 兴国县| 灵武市| 松阳县| 宁国市| 双江| 乐业县| 柳州市| 上林县| 浠水县| 全州县| 穆棱市| 常山县| 故城县| 平谷区| 柞水县| 兴义市| 东阿县| 南昌县| 化德县| 达尔| 信宜市| 汝州市| 赤峰市| 石景山区| 福安市| 习水县| 东城区| 浠水县| 岳池县| 新巴尔虎左旗| 罗江县| 庆城县| 尉犁县| 高阳县| 洮南市|