【Android 应用开发】 Android 相关代码规范 更新中 ...
.
简介 : Android 常用的代码结构, 包括包的规范, 测试用例规范, 数据库模块常用编写规范;
参考 : 之前写的一篇博客 【Android 应用开发】 Application 使用分析 ;
-- Application 分析 : Application 概念, 声明周期, 组件间传递数据作用, 数据缓存作用;
-- 源码分析 : 分析 Application 结构接口源码;
-- 使用示例 : 自定义 Application 注册, 保存崩溃日志到文件, 监听Activity声明周期;
一. 包结构规范
1. 基本包, 业务包, 测试包
包基础结构 :
-- base 包 : 应用中常用的公共包 和 类放在该包中, 例如 工具类, SQLiteOpenHelper, 配置类, Application, 各种类的基类 等;
-- business 包 : 应用中的实际业务包, 这个包存放 与 app 业务相关的具体实现的类 和 包;
-- test 包 : 用于存放单元测试 和 测试用例相关的包;
示例 :
2. 根据类型将 Java 类 分入不同包中
UI 相关 :
-- activity : 存放 Activity 相关的包;
-- fragment : 存放 Fragment 相关类;
-- widget : 存放自定义组件相关类;
适配器相关 :
-- adapter : 各种适配器, 尤其是 BaseAdapter 子类;
Java Bean相关 : 下面的两种包名经常存放 JavaBean 对象;
-- bean :
-- domain :
工具类相关 :
-- utils : 存放工具类;
监听器相关 :
-- listener : 存放各种监听器, 如按钮点击监听器等等;
数据库相关 :
-- sqlite : 存放数据库相关的包;
业务相关 :
-- engine : 存放业务逻辑相关类;
二. Application 代码规范
1. Application 单例规范
单例属性 : 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; }
2. Application 用于组件间数据传递 和 数据缓存
在 【Android 应用开发】 Application 使用分析 博客中有这方面的讲解;
Application 组件间数据传递 , Application 数据缓存;
3. 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; } }
三. 数据库模块代码常用结构
1. SQLiteOpenHelper 类
(1) 命令 版本号
类命名 : 一般命令为 XXOpenHelper, 例如 DBOpenHelper;
版本号 : 在类中定义一个常量, 用于保存版本号;
private static final int DATABASE_VERSION = 1;
(2) 单例模式
单例 : 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; }
(3) SQL 语句字段名维护
字段名使用 :
-- SQLiteOpenHelper 中的字段 : 建立数据库需要字段名称;
-- JavaBean 中的字段 : 在代码中经常用到字段名称, 一般规律是 在JavaBean 中的变量名 与 数据库中字段名相同, 字段名在 JavaBean 中需要使用, 用于从 Cursor 中获取对象;
-- Dao 中的字段 : 在插入数据时, 也许要字段名称;
维护字段名称常量 : 个人认为字段名称常量维护在 JavaBean 中最好, 这样就可以将所有的字段名都限制在 JavaBean 类中, 其它位置不用关心字段名称;
(4) SQLiteOpenHelper 代码示例
/** * 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; } } }
2. Dao 类规范
该类作用 : 将对数据库增删查改的操作都放在该类中;
(1) 维护 SQLiteOpenHelper 变量
维护变量 : 在 Dao 类中, 维护该变量, 方法中使用 OpenHelper 快速获取数据库;
(2) 在方法中实时获取 SQLiteDatabase 变量
获取数据库对象 : 如果对数据库进行操作时, 需要在方法中根据需求获取 dbHelper.getWritableDatabase() 或者 dbHelper.getReadableDatabase() 数据库对象;
(3) Dao 代码示例
/** * 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); } } }
.
【Android 应用开发】 Android 相关代码规范 更新中 ...的更多相关文章
- 知道创宇爬虫题--代码持续更新中 - littlethunder的专栏 - 博客频道 - CSDN.NET
知道创宇爬虫题--代码持续更新中 - littlethunder的专栏 - 博客频道 - CSDN.NET undefined 公司介绍 - 数人科技 undefined
- android开发常用组件【持续更新中。。。】
UI相关 图片 Android-Universal-Image-Loader:com.nostra13.universalimageloader:异步加载.缓存.显示图片 ImageLoader:co ...
- 新手开发android容易出现的错误(不断更新中...)
才开始开发android app,因为以前一直是java开发,学习也比较容易. 记录下自己开发过程中出现的一些小问题: 静态变量 在开发中,因为习惯性的问题,经常将一些常用数据(如用户信息等)进行st ...
- 码农人生——从未学过Android如何开发Android App 案例讲解-第002期案例
标题有点晃眼,本次分享是002期博文的实践故事,不会有任何代码.也不会教别人android 如何开发,类似博文已经有大批大批,而且还会有陆陆续续的人写,我写的文章,主要是经验之谈,希望总结出的一些方法 ...
- android studio 开发android app 真机调试
大家都知道开发android app 的时候可以有2种调试方式, 一种是Android Virtual Device(虚拟模拟器) ,另一种就是真机调试. 这里要说的是真机调试的一些安装步骤: 1. ...
- Android UI开发第二十八篇——Fragment中使用左右滑动菜单
Fragment实现了Android UI的分片管理,尤其在平板开发中,好处多多.这一篇将借助Android UI开发第二十六篇——Fragment间的通信. Android UI开发第二十七篇——实 ...
- Android混合开发,html5自己主动更新爬过的坑
如今使用混合开发的公司越来越多,尽管出现了一些新技术,比方Facebook的react native.阿里的weex,但依旧阻挡不了一些公司採用h5的决心.当然,这也是从多方面考虑的选择. 在三年前就 ...
- Android Studio开发Android问题集【持续更新】
问题一:emulator:ERROR:This AVD's configuration is missing a kernel file!! 答:打开Android SDK Manager,查看相应的 ...
- 用Android Studio 开发Android应用
目前AndroidStudio已经到了1.2版本了,我用了下,觉得还蛮好的,有些自动生成的资源,它会自动帮你管理.下面开始列一下,我的开发环境搭配.在开始前,你得有个VPN,可者代理.嗯.不然你下不了 ...
随机推荐
- 遗传算法:N皇后
N皇后问题描述 N皇后问题是一个经典的问题,在一个N*N的棋盘上放置N个皇后,每行一个并使其不能互相攻击(同一行.同一列.同一斜线上的皇后都会自动攻击). 遗传算法 遗传算法是局部束搜索的变形: 与自 ...
- Spring MVC运行流程
一.配置阶段 ①web.xml ②DispatcherServlet //Spring MVC总入口 ③配置初始化参数 //classpath:application.xml,用于配置无数个 ...
- 11.QT-布局管理器(Box,Grid,Form,Stacked)
布局管理器简介 QT中提供了对界面组件进行布局管理的类,用于对界面组件进行管理, 能够自动排列窗口中的界面组件 窗口大小变化后,便会自动更新界面组件的大小. 布局管理器可以自定义,从而达到更加个性化界 ...
- numpy.squeeze()是干啥的
例子: a = 3 print np.squeeze(a) # 输出3 a = [3] print np.squeeze(a) # 输出3 a = [[3]] print np.squeeze(a) ...
- Python中将一个对象倒序输出的4种方法
Python中将一个对象倒序输出的4种方法就用列表来举例说明吧: >>> lst = [1,2,3,4,5,6] #创建测试列表 #方法1: >>> lst.rev ...
- CentOS 7安装Python3.5,并与Python2.7兼容并存
CentOS7默认安装了python2.7.5,当需要使用python3的时候,可以手动下载Python源码后编译安装.1.安装python3.5可能使用的依赖1 yum install openss ...
- SpringMVC之Ajax与Controller交互
前面学习了拦截器,通过拦截器我们可以拦截请求,做进一步处理之后再往下进行,这里我们使用Ajax的时候会有一个问题就是会把js.css这些静态资源文件也进行了拦截,这样在jsp中就无法引入的静态资源文件 ...
- Studio 一些使用
1,配置: W:\android_tools\AndroidStudio2.1.3_SDK\android-studio-ide-141.2456560-windows\android-studio\ ...
- 有两个序列a,b,大小都为n,序列元素的值是任意整数,无序。
要求:通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小. 例如: var a=[100,99,98,1,2, 3]; var b=[1, 2, 3, 4,5,40]. in ...
- JAVA面向对象-----super关键字
JAVA面向对象-–super关键字 1:定义Father(父类)类 1:成员变量int x=1; 2:构造方法无参的和有参的,有输出语句 2:定义Son类extends Father类 1:成员变量 ...