(c)hele 一、基本情況 (一)開發工具改版 在我的上篇博客里,工程構建還是Eclipse模式,但是這篇博客寫出來時工程已經改為Android Studio模式,主要是Gradle工具的應用,特別是第三方庫的引用,不用將庫放進libs文件夾下,只需要進行Gradle依賴配置,十分方便。 (二)內 ...
(c)hele
一、基本情況
(一)開發工具改版
在我的上篇博客里,工程構建還是Eclipse模式,但是這篇博客寫出來時工程已經改為Android Studio模式,主要是Gradle工具的應用,特別是第三方庫的引用,不用將庫放進libs文件夾下,只需要進行Gradle依賴配置,十分方便。
(二)內置了資料庫
加入了選考科目資料庫。選考科目只有優秀、良好、及格、不及格的相關評級,不用像必考科目那樣通過內插算出分數。首先是通過選考科目界面進入查詢、添加、修改、刪除相關邏輯層操作,然後是邏輯層轉化為對數據層的操作,再次是資料庫表的欄位的選擇以及資料庫的創建,最後是資料庫在首次安裝的覆蓋寫入。
(三)使用Material Design風格界面
二、具體實現
(一)Eclipse模式到Android Studio模式
開發工具沒有變,依然是AIDE,只是我把文件結構稍做調整。如圖:是工程根目錄, 是app目錄, 是src目錄,也就是我的工程的主要部分。其中java目錄裝的是各種*.java文件,res裝和是layout、menu、string、style等文件。工程根目錄里的build.gradle文件以及settings.gradle文件則可以從新創建的gradle工程直接拷貝。 需要著重強調的是app目錄里的build.gradle文件的書寫:
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion "22.2.0"
defaultConfig {
applicationId "mtn.plaust.pe"
minSdkVersion 14
targetSdkVersion 22
versionCode 5
versionName "3.0.1"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:support-v4:22.2.0'
compile 'com.android.support:appcompat-v7:22.2.0'
compile 'com.android.support:design:22.2.0'
}
主要是dependencies的書寫,這裡引用了三個庫。
(二)資料庫實現
1. 數據結構
新建了一個PEStandard類作為數據模型:
public class PEStandard implements Serializable {
private String name, other;
private int positive, ageCode, type, male;
private Double[] standard = new Double[3];
private final static String[] STANDESC = {"優秀","良好","及格","不及格"};
public PEStandard(String name, int ageCode, int type, int male, double p1, double p2, double p3, String other) {
this.name = name; //名稱
this.ageCode = ageCode; //年齡編碼
this.type = type; //類型
this.male = male; //1代表男性,0代表女性
standard[0] = p1; //優秀
standard[1] = p2; //良好
standard[2] = p3; //及格
this.other = other; //備註,用於輸入的記錄
if (p1 > p2) { //標記正序
positive = 1;
} else {
positive = -1;
}
}
...
...
/*給定成績p,得出評定*/
public String judge(double p) {
if (p == 0)
return "";
int i;
for (i = 0; i < 3 && positive * p < positive * standard[i]; i++) {}
return STANDESC[i];
}
}
2. 表示層和邏輯層
三個文件:CustomActivity.java、CustomAddActivity.java、CustomEditActivity.java,不需要贅述。
3.數據層
public class PEStandardSqliteHelper extends SQLiteOpenHelper {
private final static String TBNAME = "t_pestandard"; //固定數據表名稱
private static SQLiteDatabase pesDB = null;
private PEStandardSqliteHelper(Context context) { //打開資料庫pe.db(版本號1)
super(context,"pe.db",null,1);
Log.i("資料庫操作","打開");
}
public static SQLiteDatabase getInstance(Context context) {
if (pesDB == null || !pesDB.isOpen()) { //懶漢模式
pesDB = new PEStandardSqliteHelper(context).getReadableDatabase();
}
return pesDB;
}
@Override
public void onCreate(SQLiteDatabase db) { //首次使用則自動調用此函數創建數據表
String sql = "create table " + TBNAME + " (name text not null, ageCode integer not null, type integer not null, male integer not null, st1 real not null, st2 real not null, st3 real not null, other text)";
db.execSQL(sql);
Log.i("資料庫操作", "創建表");
}
public static List query(int ageCode, int type, int male) {
Log.i("資料庫操作", "查詢");
//TODO:資料庫查詢
List list = new ArrayList<PEStandard>();
Cursor c = pesDB.rawQuery("select * from " + TBNAME +" where ageCode=? and type=? and male=?" ,new String[] {String.valueOf(ageCode), String.valueOf(type), String.valueOf(male)});
c.moveToFirst();
while (!c.isAfterLast()) {
list.add(new PEStandard(c.getString(0),c.getInt(1),c.getInt(2),c.getInt(3),c.getDouble(4),c.getDouble(5),c.getDouble(6),c.getString(7)));
c.moveToNext();
}
c.close();
return list;
}
public static boolean save(PEStandard p) {
//TODO:資料庫存儲
Log.i("資料庫操作","save " + p.getName());
ContentValues values = new ContentValues();
values.put("name",p.getName());
values.put("ageCode",p.getAgeCode());
values.put("type",p.getType());
values.put("male",p.getMale());
values.put("st1",p.getStandard()[0]);
values.put("st2",p.getStandard()[1]);
values.put("st3",p.getStandard()[2]);
values.put("other",p.getOther());
if (pesDB.insert(TBNAME,null,values) == -1)
return false;
return true;
}
public static boolean edit(PEStandard p) {
//TODO:資料庫修改
Log.i("資料庫操作","edit " + p.getName());
ContentValues values = new ContentValues();
values.put("st1",p.getStandard()[0]); //獲取優秀標準
values.put("st2",p.getStandard()[1]); //獲取良好標準
values.put("st3",p.getStandard()[2]); //獲取及格標準
values.put("other",p.getOther()); //備註
if (pesDB.update(TBNAME,values,"name=? and ageCode=? and type=? and male=?", new String[]{p.getName(),String.valueOf(p.getAgeCode()),String.valueOf(p.getType()),String.valueOf(p.getMale())}) > 0)
return true;
return false;
}
public static boolean delete(String name, int ageCode, int type, int male) {
//TODO:資料庫刪除
Log.i("資料庫操作","delete " + name);
if (pesDB.delete(TBNAME,"name=? and ageCode=? and type=? and male=?",new String[]{name,String.valueOf(ageCode),String.valueOf(type),String.valueOf(male)}) > 0)
return true;
return false;
}
@Override
protected void finalize() throws Throwable {
pesDB.close();
Log.i("資料庫操作","關閉");
super.finalize();
}
}
4.資料庫首次安裝覆蓋寫入
public class DBManager {
private static final int BUFFER_SIZE = 1024;
public static void initial(Context context) {
try {
BufferedInputStream bufferIn = new BufferedInputStream(context.getResources().openRawResource(R.raw.pe_db)); //從提前放入raw文件夾的pe_db讀取資料庫
byte[] temp = new byte[BUFFER_SIZE];
File file = new File(context.getCacheDir().getParentFile().getAbsolutePath()+"/databases");
if (!file.exists())
file.mkdir();
file = new File(file.getAbsolutePath()+"/pe.db");
BufferedOutputStream bufferOut = new BufferedOutputStream(new FileOutputStream(file));
int c = 0;
while ((c = bufferIn.read(temp)) > 0) {
bufferOut.write(temp,0,c);
}
bufferIn.close();
bufferOut.close();
Log.i("資料庫操作","初始化");
} catch (FileNotFoundException ex) {
Log.e("FileOperation",ex.toString());
} catch (IOException ex) {
Log.e("FileOperation",ex.toString());
}
}
}
至於如何保證首次安裝調用該類,其實跟首次登陸提示幫助一樣,要利用SharedPreference類。
(三)採用Material Design Support Library
1、Toolbar之工具條
<!--app_bar.xml-->
<android.support.design.widget.AppBarLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:fitsSystemWindows="true">
<android.support.v7.widget.Toolbar
android:id="@+id/tb"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:contentScrim="?attr/colorPrimary"
app:title="@string/app_name"/>
</android.support.design.widget.AppBarLayout>
<!--main.xml-->
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity"
android:id="@+id/draw_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<!--內容區-->
<android.support.design.widget.CoordinatorLayout
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
android:id="@+id/app_bar"
layout="@layout/app_bar"/>
...
...
2、DrawerLayout之側邊欄菜單
<!--main.xml-->
...
...
<!--左側導航欄--> <android.support.design.widget.NavigationView
android:id="@+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/navigation_header"
app:menu="@menu/options"/>
...
...
<!--options.xml-->
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item
android:id="@+id/xinbing"
android:icon="@android:drawable/ic_menu_myplaces"
android:title="@string/xinbing"/>
<item
android:id="@+id/navigation_about"
android:icon="@android:drawable/ic_menu_info_details"
android:title="@string/about"/>
<item
android:id="@+id/navigation_help"
android:icon="@android:drawable/ic_menu_help"
android:title="@string/help"/>
<item
android:id="@+id/navigation_exit"
android:icon="@android:drawable/ic_menu_set_as"
android:title="@string/exit"/>
</group>
</menu>
然後是在main.xml里添加相應的事件響應代碼。
(四)遠程Git倉庫同步
1. 在Git OSChina中創建空白git倉庫
1. 在本地.git/config進行配置
[core]
repositoryformatversion = 0
filemode = false
logallrefupdates = true
autocrlf = false
[branch "master"]
remote = master
merge = refs/heads/master
[remote "master"]
url = [email protected]:hele_two/PE
fetch = refs/heads/master
[remote "origin"]
url = [email protected]:hele_two/PE