.java
簡介 : Android 經常使用的代碼結構, 包括包的規範, 測試用例規範, 數據庫模塊經常使用編寫規範;android
參考 : 以前寫的一篇博客 【Android 應用開發】 Application 使用分析 ;git
-- Application 分析 : Application 概念, 聲明週期, 組件間傳遞數據做用, 數據緩存做用;sql
-- 源碼分析 : 分析 Application 結構接口源碼;數據庫
-- 使用示例 : 自定義 Application 註冊, 保存崩潰日誌到文件, 監聽Activity聲明週期;express
包基礎結構 : apache
-- base 包 : 應用中經常使用的公共包 和 類放在該包中, 例如 工具類, SQLiteOpenHelper, 配置類, Application, 各類類的基類 等;緩存
-- business 包 : 應用中的實際業務包, 這個包存放 與 app 業務相關的具體實現的類 和 包;app
-- test 包 : 用於存放單元測試 和 測試用例相關的包;框架
示例 :
UI 相關 :
-- activity : 存放 Activity 相關的包;
-- fragment : 存放 Fragment 相關類;
-- widget : 存放自定義組件相關類;
適配器相關 :
-- adapter : 各類適配器, 尤爲是 BaseAdapter 子類;
Java Bean相關 : 下面的兩種包名常常存放 JavaBean 對象;
-- bean :
-- domain :
工具類相關 :
-- utils : 存放工具類;
監聽器相關 :
-- listener : 存放各類監聽器, 如按鈕點擊監聽器等等;
數據庫相關 :
-- sqlite : 存放數據庫相關的包;
業務相關 :
-- engine : 存放業務邏輯相關類;
單例屬性 : Application 自己就是單例模式, 在整個應用中, 只存在一個 Application 對象;
實現 Application 單例 :
-- 定義 Application 類型對象 : 在 自定義的 Application 中定義一個 Application 類型的函數;
private static QIApplication INSTANCE;-- 定義共有構造方法 :
/** * 構造方法構造 Application */ public QIApplication() { INSTANCE = this; }-- 公共, 靜態方法獲取對象 : 在任何類中, 均可以調用該方法, 獲取 Application 上下文對象;
/** * 獲取 Application 使用該函數能夠在任意位置獲取 Application 中的數據 * @return */ public static QIApplication getInstance() { return INSTANCE; }
在 【Android 應用開發】 Application 使用分析 博客中有這方面的講解;
Application 組件間數據傳遞 , Application 數據緩存;
代碼示例 :
public class MyApplication extends Application { private static MyApplication INSTANCE; /** 用於數據傳遞的 Map 集合 */ private Map<String, Object> transferMap; /** 用於緩存數據的 Map 集合 */ private Map<String, Object> cacheMap; /** * 構造方法構造 Application */ private MyApplication() { INSTANCE = this; } /** * 獲取 Application 使用該函數能夠在任意位置獲取 Application 中的數據 * @return */ public static MyApplication getInstance() { return INSTANCE; } @Override public void onCreate() { super.onCreate(); // 初始化用於數據傳遞的 Map 集合 transferMap = new HashMap<String, Object>(); // 初始化用於數據緩存的 Map 集合 cacheMap = new HashMap<String, Object>(); } /** * 獲取數據傳遞 Map 集合 * @return * 數據傳遞 Map 集合 */ public Map<String, Object> getTransferMap() { return transferMap; } /** * 向 transferMap 集合中添加數據元素 */ public void putTransferMapElement(String key, Object object) { transferMap.put(key, object); } public Object getTransferMapElement(String key) { return transferMap.get(key); } /** * 向 transferMap 數據中移除對應的數據元素 */ public void removeTransferMapElement(String key) { transferMap.remove(key); } /** * 獲取數據緩存 Map 集合 * @return * 數據緩存 Map 集合 */ public Map<String, Object> getCacheMap() { return cacheMap; } }
類命名 : 通常命令爲 XXOpenHelper, 例如 DBOpenHelper;
版本號 : 在類中定義一個常量, 用於保存版本號;
private static final int DATABASE_VERSION = 1;
單例 : SQLiteOpenHelper 類, 在應用中只保存一個對象便可;
-- 私有, 靜態化本類成員變量 : 例如該類類名爲 DBOpenHelper, 那麼定義一個 DBOpenHelper 的成員變量, 注意將改變量設置成靜態變量;
private static DbOpenHelper instance;-- 私有化構造函數 : 將構造函數設置爲私有函數;
private DbOpenHelper(Context context) { super(context, getUserDatabaseName(), null, DATABASE_VERSION); }
-- 共有, 靜態 方法獲取成員變量 : 使用懶漢模式, 若是 本類類型成員變量 爲null, 就調用私有的靜態構造方法, 若是不爲null, 就直接返回 本類類型靜態變量;
public static DbOpenHelper getInstance(Context context) { if (instance == null) { instance = new DbOpenHelper(context.getApplicationContext()); } return instance; }
字段名使用 :
-- SQLiteOpenHelper 中的字段 : 創建數據庫須要字段名稱;
-- JavaBean 中的字段 : 在代碼中常常用到字段名稱, 通常規律是 在JavaBean 中的變量名 與 數據庫中字段名相同, 字段名在 JavaBean 中須要使用, 用於從 Cursor 中獲取對象;
-- Dao 中的字段 : 在插入數據時, 也許要字段名稱;
維護字段名稱常量 : 我的認爲字段名稱常量維護在 JavaBean 中最好, 這樣就能夠將全部的字段名都限制在 JavaBean 類中, 其它位置不用關心字段名稱;
/** * Copyright (C) 2013-2014 EaseMob Technologies. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.easemob.chatuidemo.db; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; import com.easemob.applib.controller.HXSDKHelper; public class DbOpenHelper extends SQLiteOpenHelper{ private static final int DATABASE_VERSION = 1; private static DbOpenHelper instance; private static final String USERNAME_TABLE_CREATE = "CREATE TABLE " + UserDao.TABLE_NAME + " (" + UserDao.COLUMN_NAME_NICK +" TEXT, " + UserDao.COLUMN_NAME_ID + " TEXT PRIMARY KEY);"; private static final String INIVTE_MESSAGE_TABLE_CREATE = "CREATE TABLE " + InviteMessgeDao.TABLE_NAME + " (" + InviteMessgeDao.COLUMN_NAME_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + InviteMessgeDao.COLUMN_NAME_FROM + " TEXT, " + InviteMessgeDao.COLUMN_NAME_GROUP_ID + " TEXT, " + InviteMessgeDao.COLUMN_NAME_GROUP_Name + " TEXT, " + InviteMessgeDao.COLUMN_NAME_REASON + " TEXT, " + InviteMessgeDao.COLUMN_NAME_STATUS + " INTEGER, " + InviteMessgeDao.COLUMN_NAME_ISINVITEFROMME + " INTEGER, " + InviteMessgeDao.COLUMN_NAME_TIME + " TEXT); "; private DbOpenHelper(Context context) { super(context, getUserDatabaseName(), null, DATABASE_VERSION); } public static DbOpenHelper getInstance(Context context) { if (instance == null) { instance = new DbOpenHelper(context.getApplicationContext()); } return instance; } private static String getUserDatabaseName() { return HXSDKHelper.getInstance().getHXId() + "_demo.db"; } @Override public void onCreate(SQLiteDatabase db) { db.execSQL(USERNAME_TABLE_CREATE); db.execSQL(INIVTE_MESSAGE_TABLE_CREATE); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } public void closeDB() { if (instance != null) { try { SQLiteDatabase db = instance.getWritableDatabase(); db.close(); } catch (Exception e) { e.printStackTrace(); } instance = null; } } }
該類做用 : 將對數據庫增刪查改的操做都放在該類中;
維護變量 : 在 Dao 類中, 維護該變量, 方法中使用 OpenHelper 快速獲取數據庫;
獲取數據庫對象 : 若是對數據庫進行操做時, 須要在方法中根據需求獲取 dbHelper.getWritableDatabase() 或者 dbHelper.getReadableDatabase() 數據庫對象;
/** * Copyright (C) 2013-2014 EaseMob Technologies. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.easemob.chatuidemo.db; import java.util.HashMap; import java.util.List; import java.util.Map; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.text.TextUtils; import com.easemob.chatuidemo.Constant; import com.easemob.chatuidemo.domain.User; import com.easemob.util.HanziToPinyin; public class UserDao { public static final String TABLE_NAME = "uers"; public static final String COLUMN_NAME_ID = "username"; public static final String COLUMN_NAME_NICK = "nick"; public static final String COLUMN_NAME_IS_STRANGER = "is_stranger"; private DbOpenHelper dbHelper; public UserDao(Context context) { dbHelper = DbOpenHelper.getInstance(context); } /** * 保存好友list * * @param contactList */ public void saveContactList(List<User> contactList) { SQLiteDatabase db = dbHelper.getWritableDatabase(); if (db.isOpen()) { db.delete(TABLE_NAME, null, null); for (User user : contactList) { ContentValues values = new ContentValues(); values.put(COLUMN_NAME_ID, user.getUsername()); if(user.getNick() != null) values.put(COLUMN_NAME_NICK, user.getNick()); db.replace(TABLE_NAME, null, values); } } } /** * 獲取好友list * * @return */ public Map<String, User> getContactList() { SQLiteDatabase db = dbHelper.getReadableDatabase(); Map<String, User> users = new HashMap<String, User>(); if (db.isOpen()) { Cursor cursor = db.rawQuery("select * from " + TABLE_NAME /* + " desc" */, null); while (cursor.moveToNext()) { String username = cursor.getString(cursor.getColumnIndex(COLUMN_NAME_ID)); String nick = cursor.getString(cursor.getColumnIndex(COLUMN_NAME_NICK)); User user = new User(); user.setUsername(username); user.setNick(nick); String headerName = null; if (!TextUtils.isEmpty(user.getNick())) { headerName = user.getNick(); } else { headerName = user.getUsername(); } if (username.equals(Constant.NEW_FRIENDS_USERNAME) || username.equals(Constant.GROUP_USERNAME)) { user.setHeader(""); } else if (Character.isDigit(headerName.charAt(0))) { user.setHeader("#"); } else { user.setHeader(HanziToPinyin.getInstance().get(headerName.substring(0, 1)) .get(0).target.substring(0, 1).toUpperCase()); char header = user.getHeader().toLowerCase().charAt(0); if (header < 'a' || header > 'z') { user.setHeader("#"); } } users.put(username, user); } cursor.close(); } return users; } /** * 刪除一個聯繫人 * @param username */ public void deleteContact(String username){ SQLiteDatabase db = dbHelper.getWritableDatabase(); if(db.isOpen()){ db.delete(TABLE_NAME, COLUMN_NAME_ID + " = ?", new String[]{username}); } } /** * 保存一個聯繫人 * @param user */ public void saveContact(User user){ SQLiteDatabase db = dbHelper.getWritableDatabase(); ContentValues values = new ContentValues(); values.put(COLUMN_NAME_ID, user.getUsername()); if(user.getNick() != null) values.put(COLUMN_NAME_NICK, user.getNick()); if(db.isOpen()){ db.replace(TABLE_NAME, null, values); } } }
.