一樣是小一上學期剛學的時候玩的作品

因為很喜歡地球科學、太空主題自己設計的奇妙小動畫

這次的作品他自己加了很多角色(雲)😄😄😄

同時讓兩個角色:人和龍捲風一起移動

比較有趣的是他自己發現可以更換角色裡面部分圖案用自己拍的照片取代..

小朋友真的是比大人厲害多了!!

這次使用的程式方塊除了移動、旋轉,放大縮小外,還使用了加速...

Screenshot_20190907-082115.jpg

Screenshot_20190907-082122.jpg

文章標籤

muchone 發表在 痞客邦 留言(0) 人氣()

這是兒子小一上學期剛開始接觸Scratch Jr.的第一個成品

姑且叫做太空人漫遊吧...

完全的自由發揮,很有趣,真的很喜歡看小朋友自己的創意!!

因為研究了半天不知道scratch jr.要怎麼把專案上傳,

最後決定用影片錄製的方式做紀錄...

這是程式方塊的排列...

大致運用了放大縮小,旋轉,時間停止,錄音播放的方塊....

希望有機會能遇到也喜歡的小朋友可以一起討論...

scratch jr.

文章標籤

muchone 發表在 痞客邦 留言(0) 人氣()

最近公司要求要學習開發window平台軟體..

可以選擇使用C#或MFC,

一個月內要有產出...

想了以後覺得MFC對菜不啦嘰的我來說進入障礙太高了...

還是選擇據說跟JAVA很像的C#...

選了以後發現不但要學C#還要學MPF...各種困難...

而且說像也不是真的完全一樣,還是有很多不同之處需要琢磨呀...

先把練習的筆記整理起來備用吧....

 


 
*關於字串的使用
 
(一)宣告字串變數:
string a="kelly";
 
(二)字串插補:
在字串前加上"$"符號,並用{}括住變數
Console.WriteLine($"Hello { aFriend}");
 
字串插補印出來的效果等同於
Console.WriteLine("Hello"+aFriend);
 
在整個字串中並不限制只能使用一個大括號
string firstFriend = "Maria";
string secondFriend = "Sage";
Console.WriteLine($"My friends are {firstFriend} and {secondFriend}");
 
(三)字串屬性:
Length=>字串長度
Console.WriteLine($"The name {firstFriend} has {firstFriend.Length} letters.");
Console.WriteLine($"The name {secondFriend} has {secondFriend.Length} letters.");
 
其他字串屬性可以查詢連結文件
 
字串的方法
 
 
*關於數字的使用
 
(一)int整數(可為正整數或負整數):
- 用於減法
* 用於乘法
/ 用於除法
% 取得餘數
 
數學運算的優先順序,乘法和除法的優先順序高於加法和減法。    
 
int 型別有最小和最大限制。 (java亦同)
int max = int.MaxValue;
int min = int.MinValue;
Console.WriteLine($"The range of integers is {min} to {max}");
 
 
(二)Double 雙精確度浮點數:
double a = 19;
double b = 23;
double c = 8;
double d = (a  + b) / c;
Console.WriteLine(d);
 
(三)decimal固定點型別:
decimal的範圍較小,但精確度較 double 來得高。 固定點這個詞代表小數點 (或二進位點) 不會移動。
 
double a = 1.0;
double b = 3.0;
Console.WriteLine(a / b);
 
 
decimal c = 1.0M;
decimal d = 3.0M;
Console.WriteLine(c / d);
M 尾碼乃是指示常數應使用 decimal 型別
 
 
文章標籤

muchone 發表在 痞客邦 留言(0) 人氣()

從自己開始學程式開始,就覺得寫程式是一件很有趣的事情...

這麼好玩的事當然也希望兒子能一起體驗...

也上網看了不少兒童學習程式的介紹、軟體、發展等等...

自己也看了一些教程像是Code.org...研究了一下外面補習班的課程與費用...

不過因為一直擔心小孩會因為花太多時間在3C產品上變得不愛念書或近視等問題...

遲遲沒有讓他接觸這一塊...

上了小學以後,發現學校也有這樣的才藝課--Scratch Jr.

一個專門給7~8歲小朋友學的簡易程式學習APP

之前有了解過Scratch,想不到還有Jr.版,忍不住就想要讓兒子試試看!

不過怕他沒接觸過程式,擔心突然要跟他解釋他不能理解

所以,在嘗試之前也有先讓兒子接觸過一些簡單的程式邏輯app

像是

Code-a-pillar:免費軟體,最先開始就是用這個練手,很可愛又很容易上手

code-a-pillar

code karts:要付費才能開啟比較多關卡,越後面會越難

code karts

Lightbot:免費,但是難度比前兩個高

Lightbot

所以他對於程式指令還算有一點小小的概念

本來是想讓他在學校上才藝課就可以比較完整的把課程上完

但那堂才藝課超熱門根本搶不到...想一想其實也不難乾脆自己教?

一開始確實還去很認真地研究了教學,希望能比較有系統的教他,

但一來是下班還是有點累,後來也比較忙,

就只有一開始有趁六日教他基本的指令用法...

讓他試著思考怎麼用...

後來有讓他睡覺前自己摸索一下功能自己做一下小作品...

剛開始他也是充滿興趣,每天都玩得很開心...

但後來可能我沒有引導他,他也不知道該怎麼繼續,

漸漸就沒興趣了...覺得有點可惜

後來為了讓他再次對這個有興趣,還買了樂高機器人lego boost,

Lego boost

有專屬的說明書與控制app

還有一個額外購買的藍芽裝置,據說安裝後可以使用scratch程式來控制它

Lego boost

這也是利用程式來操控機器人的做法,

但是跟scratch jr.一樣,沒有人引導很快就放棄...

倒不是因為太難或不會,而是不知道要怎麼去變化更多玩法...

會很快就膩了...

終於等到這次暑假,剛好第一個月沒甚麼事,怕他在家太無聊...

於是先利用樂高機器人的有趣性..

讓他先把機器人操作app教學中所有練習都做完...

我發現小孩真的創意無窮,

本來擔心他可能會說太難都不認真做,

想不到意外地做得很好...

等他都練習完我就給他一些主題要他自己完成,

也都做得很好,

之後就再次帶入scratch jr.

下載了一些網站上的教學給他練習

也都有完成,後面要自己發想的東西也有認真思考,

每天下班回家跟他討論,覺得真的很不錯...

所以決定來分享並記錄一下他的小作品

 

**補充資料:

Scratch Jr.官網:官網上有很多資源可以使用,如果有興趣可以上去研究一下

如果擔心不知道從哪下手,開始之前可以先看一下 Things to Try on ScratchJr

一開始是介紹Scratch,要拉到下面才有Scrtatch Jr.

裡面就有講到,有activity cards練習,也有sample project

都是很不錯的學習資源喔!

 

 

 

 

 

 

 

 

 

文章標籤

muchone 發表在 痞客邦 留言(0) 人氣()

覺得這應該是一個非常冷門的東西...

但我和我們家兒子都非常熱愛裡面有藏玩具的沐浴球....

以前大創或是彩遊館可以買的到...現在都找不到了...

老公去德國...發現德國也有...

本來沒有要請老公代買,因為太重了...但老公還是買了給兒子驚喜...

實在很好奇和日本的差別在哪...

所以決定來一篇開箱文 哈~

沐浴球

可以看的出來裡面種共會有六種可能出現的海底生物...

最想要的是海豚和烏龜...

包裝外的小青蛙也是超級可愛的!!

沐浴球

打開來以後就是一顆藍色的沐浴球...非常非常香!(全家都熱愛香味)

沐浴球

 

放到水裡,水會變成藍綠色,

沐浴球

外面有用一個小扭蛋裝起來

我們抽到的是小河豚...雖然不是最想要的,但還是好可愛呀!!

沐浴球

下次老公再去德國,應該還是會請他代購吧 哈!

德國dm可以買的到,如果真的有人對這麼冷門的東西有興趣的話...

參考網址: https://www.dm.de/tetesept-badezusatz-kinder-badespass-badeueberraschung-schatzsucher-p4008491211307.html

文章標籤

muchone 發表在 痞客邦 留言(0) 人氣()

前陣子在研究Android TV的開發,使用的TV BOX是小米盒子三增強版/小米盒子國際版/小米盒子S(國際版)

因為第一個是小米UI,跟國際版操作不太一樣,所以特別筆記一下免得忘記了...

一、開啟開法者模式

1.在小米盒子設置中選關於

小米盒子

2.對產品型號多次點擊,直到出現"您已處於開發者模式,無需進行此操作",完成開啟開發者模式

小米盒子

 

二、開啟ADB調試-可連接USB安裝apk進行測試

1.一樣進入小米盒子設置後,選擇帳號與安全

小米盒子

2.開啟ADB調試

小米盒子

 3.插上USB線後跳出,是否允許USB調試的對話框,選擇確定即完成

小米盒子

 

文章標籤

muchone 發表在 痞客邦 留言(0) 人氣()

*修改分支名稱,分為local(本機)和remote(遠端),改完本機後要先把遠端原本的分支刪除,再把修改過名稱的本機分支上傳到遠端
 
*目的:要把分支鏡像改為鏡像版for單目
1.先在Sourcetree左側的BRANCHES的鏡像按右鍵選Rename鏡像版,就可以直接修改本機的分支名稱(下圖是已經修改完成的畫面)
=>如果只改了本機的,遠端的不會同步修改
rename branch name
 
2.到下方REMOTES點開,選要修改的分支名稱"鏡像版"按右鍵,將該分支刪除
rename branch name
 
3.回到BRANCHES,對已經變更好名稱的分支"鏡像版for單目"按右鍵,選取Push to origin/鏡像版(tracked)
rename branch name
 
4.跳出push視窗,勾選要puch的分支,確定後就完成了
rename branch name
 
5.再回到左邊看REMOTES,已新增新的分支名稱為"鏡像版for單目"
rename branch name
 
文章標籤

muchone 發表在 痞客邦 留言(0) 人氣()

●程式說明

(一)DAO與SQLite的教學可參考此篇文章
 

(二)MemoryDAO Implement (關掉app就沒了,所以沒有實用性,這邊只是知道該怎麼做)
public class CusomerDAOMemoryImpl implements CustomerDAO {
    ArrayList<customer> datalist=new ArrayList<>();
    int id=1;
    @Override
    public void addOne(customer c) {
        //因為不是寫進資料庫,所以id不會自動給定,要自己寫入
        c.id this.id;
        this.id++;
        datalist.add(c);
    }
 
    @Override
    public customer getOne(int id) {
        //因為可能會找不到資料,所以會是null
        customer rtValue = null;
        //跑回圈找id對的回傳
        for (customer tmp : datalist)
        {
            if (tmp.id == id)
            {
                rtValue = tmp;
                break;
            }
        }
        return rtValue;
    }
 
    @Override
    public void clearAll() {
        datalist.clear();
    }
 
    @Override
    public customer[] getList() {
        return datalist.toArray(new customer[datalist.size()]);
    }
 
    @Override
    public void delete(customer c) {
        datalist.remove(c);
    }
 
    @Override
    public void update(customer c) {
        for (customer tmp : datalist)
        {
            if (tmp.id == c.id)
            {
                tmp.name = c.name;
                tmp.addr = c.addr;
                tmp.tel = c.tel;
                break;
            }
        }
    }
}
 
**寫測試程式,因為MemoryDAO和手機無關,可以直接寫一般的測試程式,不用寫androidTest
public class MyMemorDAOTest {
 
@Test
public void clearAndAddOneDataAndGetTest() {
CusomerDAOMemoryImpl dao = new CusomerDAOMemoryImpl();
customer c = new customer();
c.name = "BBB";
c.tel = "123";
c.addr = "aabb";
dao.clearAll();
dao.addOne(c);
customer cArray[] = dao.getList();
assertEquals("BBB", String.valueOf(cArray[0].name));
 
}
 
@Test
//測試刪除
public void testDelete1() {
CusomerDAOMemoryImpl dao = new CusomerDAOMemoryImpl();
customer c1 = new customer("ccc", "333", "123456");
customer c2 = new customer("ddd", "444", "123456");
dao.clearAll();
dao.addOne(c1);
dao.addOne(c2);
customer cArray[] = dao.getList();
//因為前面new c1時沒有給id,所以這邊設定idc1
c1.id = cArray[0].id;
dao.delete(c1);
customer cArray2[] = dao.getList();
assertEquals("ddd", cArray2[0].name);
}
@Test
//測試更新
public void testUpdate() {
CusomerDAOMemoryImpl dao = new CusomerDAOMemoryImpl();
customer c1 = new customer("ccc", "333", "123456");
 
dao.clearAll();
dao.addOne(c1);
customer carray[] = dao.getList();
c1.id = carray[0].id;
c1.name = "fff";
dao.update(c1);
customer carray2[] = dao.getList();
assertEquals("fff", carray2[0].name);
}
}
 
(三)寫到app中要大改,不能直接用舊的程式,因為memory每new一次就會是一個新的,這樣會找不到資料
(1)新增一個DAOApplication並修改mainfeast
android:name=".DAOApplication"
public class DAOApplication extends Application {
public CustomerDAO dao = new CusomerDAOMemoryImpl();
}
 
 
(2)新增一個DAOFactory
public class CustomerDAOFactory {
public static CustomerDAO getDAO(Context context, DAOType dt)
{
//因為傳進來的是ACTIVITY,要把CONTEXT轉成ACTIVITY
Activity act = (Activity) context;
DAOApplication app = (DAOApplication) act.getApplication();
CustomerDAO dao = null;
switch(dt)
{
case Memory:
dao = app.dao;
break;
case DB:
dao = new CustomerDAODBImpl(context);
break;
}
return dao;
}
}
 
 
(3)新增enum DAOType
//列舉DAO類型
public enum DAOType {
Memory,DB
}
 
 
 
(4)修改舊程式有new CustomerDAO之處
mainactivity改
 
1.在最外面宣告DAOType
//只要控制MainActivity DAOType,就可ˇ決定要存到記憶體還是資料庫
public static DAOType dt = DAOType.Memory;
 
2.
super.onResume();
CustomerDAO dao=  CustomerDAOFactory.getDAO(MainActivity.this, MainActivity.dt);
customer[] cust = dao.getList();
...
sec改
CustomerDAO cdd=  CustomerDAOFactory.getDAO(sec.this, MainActivity.dt);
customer c=new customer();
...
 
editinfo改
1.
int index=Integer.parseInt(i);
CustomerDAO dao= CustomerDAOFactory.getDAO(editeInfo.this, MainActivity.dt);
...
2.
public void delete(View view) {
    CustomerDAO dao=  CustomerDAOFactory.getDAO(editeInfo.this, MainActivity.dt);
...
3.
public void update(View view) {
    CustomerDAO dao=  CustomerDAOFactory.getDAO(editeInfo.this, MainActivity.dt);
...
 
(四)寫到json中(資料會寫在檔案中)
(1)Enum要新增File,並且把mainActivity的DAOType改為File
 
(2)新增一個class
public class CustomerDAOFileImpl implements CustomerDAO {
ArrayList<customer> datalist = new ArrayList();
String File_Name = null;
 
//要建constructor
public CustomerDAOFileImpl(Context context)
{
//因為filename在建構式中不能直接getFileDir(),因為這是我們自己寫的類別,所以要先取得activity
Activity act = (Activity) context;
File_Name = act.getFilesDir().getAbsolutePath() + File.separator + "mydata.json";
FileReader fr = null;
try {
//要確保檔案存在,檢查檔案有存在才能讀取
File f = new File(File_Name);
if (f.exists())
{
fr = new FileReader(File_Name);
BufferedReader br = new BufferedReader(fr);
String str = br.readLine();
//因為讀進來的是json檔,所以可以用gson
Gson gson = new Gson();
datalist = gson.fromJson(str, new TypeToken<ArrayList<customer>>(){}.getType());
br.close();
fr.close();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
//要新增一個寫入檔案的程式,只要有做修改最後都要做save to file的動作
private void saveFile()
{
Gson gson = new Gson();
String str = gson.toJson(datalist);
FileWriter fw = null;
try {
fw = new FileWriter(File_Name);
BufferedWriter bw = new BufferedWriter(fw);
bw.write(str);
bw.close();
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
 
@Override
public void addOne(customer c) {
datalist.add(c);
saveFile();
}
 
@Override //getOne因為沒有做修改所以不需要save to file做法就跟memory一樣
public customer getOne(int id) {
customer rtValue = null;
for (customer tmp : datalist)
{
if (tmp.id == id)
{
rtValue = tmp;
break;
}
}
return rtValue;
}
 
@Override
public void clearAll() {
datalist.clear();
saveFile();
}
 
@Override
public customer[] getList() {
return datalist.toArray(new customer[datalist.size()]);
}
 
@Override
public void delete(customer c) {
datalist.remove(c);
saveFile();
}
 
@Override
public void update(customer c) {
for (customer tmp : datalist)
{
if (tmp.id == c.id)
{
tmp.name = c.name;
tmp.addr = c.addr;
tmp.tel = c.tel;
break;
}
}
saveFile();
}
}
 

●程式參考(GitHub):透過Enum選擇Data Storage的方式(SQLite, FileWriter, Memory )

文章標籤

muchone 發表在 痞客邦 留言(0) 人氣()

●程式說明--Android Unit Test

1.androidTest:要開android設備才可以測的=>要用到android元件(可以用模擬器也可以用實機測試)
2.test: 不用開android設備就可以測的 =>純java程式
 
(一)test
*建一個MyMath class
//建一個簡單的class做測試內容
public class MyMath {
    public static int add(int x, int y) {
        return x + y;
    }
}
 
*建一個Test1 class
public class Test1 {
    //一定要加@Test,說明是在測試
    @Test
    public void myTest()
    {
        //assert如果是false,就會中斷
        //assertEquals,當兩個參數的值相等就代表測試成功
        assertEquals(10, MyMath.add(3,7));
    }
 
}
 
=>測試,到檔案按右鍵=>run
android unit test / TestCase
 
=>測試成功會是綠色的
android unit test / TestCase
 
=>測試失敗是紅色的
android unit test / TestCase
 
=>在整個測試檔上選整個專案測試,就會每個測試程式都run
android unit test / TestCase
 
(二)androidTest
=>測試新增的資料是否正確
//一定要加@RunWith,代表測試
@RunWith(AndroidJUnit4.class)
public class MyDAOTest1 {
    @Test
    public void AddandGetTest(){
        //取得context就可以建立phoneDAODBImpl物件
        Context appContext = InstrumentationRegistry.getTargetContext();
        phoneDAODBImpl dao = new phoneDAODBImpl(appContext);
        phone p = new phone();
        p.name "BBB";
        p.tel "123";
        p.addr "aabb";
        dao.addOne(p);
        phone p1 = dao.getOne(1);
        assertEquals("AA",p1.name);
    }
}
 
=>測試失敗的畫面
android unit test / TestCase
 
=>預期結果是AA但是真實結果為BBB
android unit test / TestCase
 
=>測試成功的畫面
android unit test / TestCase
 
 
//清除資料表以後重建一筆測試
@Test
public void clearAndAddOneDataAndGetTest()
{
    Context appContext = InstrumentationRegistry.getTargetContext();
    phoneDAODBImpl dao = new phoneDAODBImpl(appContext);
    phone p = new phone();
    p.name "BBB";
    p.tel "123";
    p.addr "aabb";
    //清除資料後再新增一筆測試,確保資料庫正確
    dao.clearAll();
    dao.addOne(p);
    //取得資料庫的資料放到陣列中
    phone pArray[] = dao.getList();
    //取得第一筆資料中的name來測試
    assertEquals("BBB", pArray[0].name);
 
}
 
//測試刪除
@Test
public void testDelete1(){
Context appContext = InstrumentationRegistry.getTargetContext();
phoneDAODBImpl dao = new phoneDAODBImpl(appContext);
phone p1=new phone("ccc","333","123456");
phone p2=new phone("ddd","444","123456");
dao.clearAll();
dao.addOne(p1);
dao.addOne(p2);
phone pArray[]=dao.getList();
//因為前面new c1時沒有給id,所以這邊設定idc1
p1.id=pArray[0].id;
dao.delete(p1);
phone pArray2[]=dao.getList();
assertEquals("ddd",pArray2[0].name);
}
 
//測試更新
@Test
public void testUpdate(){
Context appContext = InstrumentationRegistry.getTargetContext();
phoneDAODBImpl dao = new phoneDAODBImpl(appContext);
phone p1=new phone("ccc","333","123456");
 
dao.clearAll();
dao.addOne(p1);
phone parray[]=dao.getList();
p1.id=parray[0].id;
p1.name="fff";
dao.update(p1);
phone parray2[]=dao.getList();
assertEquals("fff", parray2[0].name);
}

 

 

●程式參考(GitHub):Android Unit Test單元測試 (測試程式與DAO和SQLite的程式放在一起)

 

文章標籤

muchone 發表在 痞客邦 留言(0) 人氣()

●程式說明--用程式建立SQLite資料庫
=>要先新增一個class繼承SQLiteOpenHelper
SQLite and DAO
 
=>SQLiteOpenHelper是一個抽象類別,所以要override兩個方法
=>還要加建構式,因為SQLiteOpenHelper這個父類別本身只有有參數的建構式,所以一定要加,不然當父類別的參數要使用到時就會有問題
=>加建構式時,選第一個
SQLite and DAO
 
=>新增欄位在add column
SQLite and DAO
 
=>複製新增欄位的語法,按下add column按鈕就會跳出對話框,語法就在對話框上
SQLite and DAO
 
(一)MyHelper.class
package com.example.student.lu101801;
 
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
 
 
public class MyHelper extends SQLiteOpenHelper {
//本來建構式繼承有四個參數,但factory用不到就直接設定null
//資料庫名稱和版本則會直接設定final然後把這三個參數丟到super方法中
//這樣mainactivity要建立MyHelper物件時,就只要丟context這個參數進來就可以
static final String DB_NAME="student.sqlite";
static final int VERSION=4;
 
public MyHelper(Context context) {
super(context, DB_NAME, null, VERSION);
}
 
@Override //如果系統中沒有這個資料庫,就會跑onCreate
public void onCreate(SQLiteDatabase sqLiteDatabase) {
//先去SQLite Manager複製create語法,這邊有個技巧事先打好雙引號再貼上語法
//這樣會自動把需要加上反斜線的內容都加好反斜線
//在做版本更新時,除了onUpgrade要加sql語法,onCreate也要加,因為可能有用戶是沒有舊版就直接安裝新版的
String createSQL="CREATE TABLE \"phone\" (\"id\" INTEGER PRIMARY KEY NOT NULL ,\"name\" VARCHAR,\"tel\" VARCHAR,\"addr\" VARCHAR DEFAULT (null) , \"email\" VARCHAR, \"tel2\" VARCHAR)";
//sqLiteDatabase是從參數帶入的SQLiteDatabase
sqLiteDatabase.execSQL(createSQL);
}
 
@Override //如果系統中有這個資料庫且版本不同,就會跑onUpgrade
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldversion, int newversion) {
Log.d("verson","verson:"+oldversion);
//因為new這個物件時會帶入版本參數,這邊就要做版本的判斷來決定要做甚麼
if (oldversion != 4 )
{
String upgradeSQL = "ALTER TABLE \"main\".\"phone\" ADD COLUMN \"tel2\" VARCHAR";
sqLiteDatabase.execSQL(upgradeSQL);
}
}
}
 
 
 
(二)phone.class
package com.example.student.lu101801;
//注意不要把public寫成static,會把屬性值改掉然後指記憶最後一筆資料
//建一個物件用來存放資料庫的資料
public class phone {
public int id;
public String name;
public String tel;
public String addr;
public String email;
public String tel2;
 
}
 
(三)MainActivity.class
public class MainActivity extends AppCompatActivity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
 
    public void click1(View view) {
        phone p=new  phone();
        p.name="kent";
        p.tel="12345678";
        p.tel2="87654321";
        p.addr="abceddddd";
        p.email="test2@eamil";
 
        add(p);
        phone p1=getOne(5);
        Log.d("p1","p1"+p1.name);
    }
    //新增資料的method
    public void add(phone p){
        //要透過建立MyHelper這個步驟來新增資料庫(沒有就onCreate/有就直接使用/要更新版本就onUpgrade)
        //這邊在宣告MyHelper的時候就run onCreate
        MyHelper helper=new MyHelper(MainActivity.this);
        //呼叫getWritableDatabase()時,就會去執行onCreate中的execSQL();
        SQLiteDatabase db=helper.getWritableDatabase();
 
        ContentValues cv = new ContentValues();
        //寫入時,每個欄位資料都去對應phone 物件的各個field
        cv.put("name",p.name);
        cv.put("tel",p.tel);
        cv.put("addr",p.addr);
        cv.put("email",p.email);
        cv.put("tel2",p.tel2);
        db.insert("phone"null, cv);
 
        db.close();
    }
 
    //讀取資料的method(會傳回phone物件)
    public phone getOne(int id){
        phone p=new  phone();
        MyHelper helper=new MyHelper(MainActivity.this);
        SQLiteDatabase db=helper.getWritableDatabase();
        //因為會帶入一個int id的參數,這邊第三第四個參數也要設定,先在第三個參數設定要如何篩選資料
        // 第四個參數是把丟進來的int id轉成字串陣列的第一筆資料再丟給id(參數3)去篩選,這樣就會找到那一筆id的資料
        Cursor c = db.query("phone",new String[] {"id","name","tel",
        "addr","email","tel2"}, "id=?"
        new String[] {String.valueOf(id)}, nullnullnull);
        c.moveToFirst();
        //設定在讀取時,phone class的每個field會去抓哪個欄位的資料
        p.id=c.getInt(0);
        p.name = c.getString(1);
        p.tel = c.getString(2);
        p.addr = c.getString(3);
        p.email=c.getString(4);
        p.tel2=c.getString(5);
        db.close();
        return p;
    }
}
**說明:
這種利用物件來進行資料庫的操作稱為ORM,而資料庫的處理和前面程式的處理分開稱為DAO
 
●DAO pattern(Design pattern)=>部分程式比照上方
(一)phoneDAO.class
//先用一個DAO定義資料庫有哪些操作(interface),再實作填寫真正的操作內容
public interface phoneDAO {
    public void  addOne(phone p);
    public phone getOne(int id);
    public void clearAll();
    public phone[] getList();
    public void delete(phone p);
    public void update(phone p);
}
 
(二)phone.class
//建一個物件用來存放資料庫的資料
public class phone {
public int id;
public String name;
public String tel;
public  String addr;
public  String email;
public  String tel2;
 
//為了不影響前面程式,要多寫幾個建構式(因為之前程式new物件的時候不用放參數)
public phone() {
}
 
 
//為了方便處理資料,加寫建構式,三個參數是用來新增物件用
public phone(String name, String tel, String addr) {
    this.name = name;
    this.tel = tel;
    this.addr = addr;
}
 
 
//四個參數是用來讀取資料用
public phone(int id, String name, String tel, String addr) {
    this.id = id;
    this.name = name;
    this.tel = tel;
    this.addr = addr;
}
}
 
 
(三) MyHelper.class
public class MyHelper extends SQLiteOpenHelper {
//本來建構式繼承有四個參數,但factory用不到就直接設定null
//資料庫名稱和版本則會直接設定final然後把這三個參數丟到super方法中
//這樣mainactivity要建立MyHelper物件時,就只要丟context這個參數進來就可以
static final String DB_NAME="student.sqlite";
static final int VERSION=4;
 
public MyHelper(Context context) {
super(context, DB_NAME, null, VERSION);
}
 
@Override //如果系統中沒有這個資料庫,就會跑onCreate
public void onCreate(SQLiteDatabase sqLiteDatabase) {
//先去SQLite Manager複製create語法,這邊有個技巧事先打好雙引號再貼上語法
//這樣會自動把需要加上反斜線的內容都加好反斜線
//在做版本更新時,除了onUpgrade要加sql語法,onCreate也要加,因為可能有用戶是沒有舊版就直接安裝新版的
String createSQL="CREATE TABLE \"phone\" (\"id\" INTEGER PRIMARY KEY NOT NULL ,\"name\" VARCHAR,\"tel\" VARCHAR,\"addr\" VARCHAR DEFAULT (null) , \"email\" VARCHAR, \"tel2\" VARCHAR)";
//sqLiteDatabase是從參數帶入的SQLiteDatabase
sqLiteDatabase.execSQL(createSQL);
}
 
@Override //如果系統中有這個資料庫且版本不同,就會跑onUpgrade
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldversion, int newversion) {
Log.d("verson","verson:"+oldversion);
//因為new這個物件時會帶入版本參數,這邊就要做版本的判斷來決定要做甚麼
if (oldversion != 4 )
{
String upgradeSQL = "ALTER TABLE \"main\".\"phone\" ADD COLUMN \"tel2\" VARCHAR";
sqLiteDatabase.execSQL(upgradeSQL);
}
}
}
 
(四)
//名稱取名為phoneDAO在DB上的實作(可以套用到雲端、檔案....)
public class phoneDAODBImpl implements phoneDAO {
SQLiteDatabase db;
MyHelper helper;
 
//因為在建立db時要取得mainactivity,所以要加一個建構是在new的時候可以把mainactivity傳進來
public phoneDAODBImpl(Context context) {
helper=new MyHelper(context);
db=helper.getWritableDatabase();
}
//刪除
@Override
public void clearAll()
{
SQLiteDatabase db = helper.getWritableDatabase();
//刪除的語法要用delete from phone,把整個table刪掉
db.execSQL("delete from phone");
db.close();
}
 
@Override
public phone[] getList() {
SQLiteDatabase db = helper.getWritableDatabase();
//建一個phone型別的arraylist
ArrayList<phone> mylist = new ArrayList();
//這邊因為要取全部的資料所以不要用where
Cursor c = db.query("phone", new String[] {"id","name","tel","addr"}, null, null, null, null, null);
if (c.moveToFirst())
{
do {
phone p = new phone();
p.id = c.getInt(0);
p.name = c.getString(1);
p.tel = c.getString(2);
p.addr = c.getString(3);
//把p的資料加到mylist中
mylist.add(p);
}while(c.moveToNext());
}
//把arraylist轉成array,而且要把這個和mylist資料長度一樣的array轉成phone型別
phone rValue[] = mylist.toArray(new phone[mylist.size()]);
return rValue;
}
 
@Override
public void addOne(phone p) {
db=helper.getWritableDatabase();
ContentValues cv = new ContentValues();
//寫入時,每個欄位資料都去對應phone 物件的各個field
cv.put("name",p.name);
cv.put("tel",p.tel);
cv.put("addr",p.addr);
cv.put("email",p.email);
cv.put("tel2",p.tel2);
db.insert("phone", null, cv);
db.close();
}
 
@Override
public phone getOne(int id) {
//要再取得一次database,因為如果先做addOne會把db關閉,這邊要再取得一次
db=helper.getWritableDatabase();
phone p=new phone();
//因為會帶入一個int id的參數,這邊第三第四個參數也要設定,先在第三個參數設定要如何篩選資料
// 第四個參數是把丟進來的int id轉成字串陣列的第一筆資料再丟給id(參數3)去篩選,這樣就會找到那一筆id的資料
Cursor c = db.query("phone",new String[] {"id","name","tel","addr","email","tel2"}, "id=?", new String[] {String.valueOf(id)}, null, null, null);
c.moveToFirst();
//設定在讀取時,phone class的每個field會去抓哪個欄位的資料
p.id=c.getInt(0);
p.name = c.getString(1);
p.tel = c.getString(2);
p.addr = c.getString(3);
p.email=c.getString(4);
p.tel2=c.getString(5);
db.close();
return p;
}
 
   //刪除
    @Override
    public void delete(phone p) {
        SQLiteDatabase db=helper.getWritableDatabase();
        //第二個參數是where clause,第三個參數是指定要刪除的那筆資料id
        db.delete("phone","id=?",new String[] {String.valueOf(p.id)});
        db.close();
    }
 
     //更新
    @Override
    public void update(phone p) {
        SQLiteDatabase db=helper.getWritableDatabase();
        ContentValues cv = new ContentValues();
        cv.put("name",p.name);
        cv.put("tel",p.tel);
        cv.put("addr",p.addr);
        cv.put("email",p.email);
        cv.put("tel2",p.tel2);
        // 第二個參數要更新的資料
        //第三個參數是要用甚麼篩選,第四個參數是要更新哪一筆資料
        db.update("phone",cv,"id=?",new String[] {String.valueOf(p.id)});
        db.close();
    }
}
 
(五)MainAcitivity.class
package com.example.student.lu101801;
 
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
 
public class MainActivity extends AppCompatActivity {
 
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
 
public void click1(View view) {
phone p=new phone();
p.name="kent";
p.tel="12345678";
p.tel2="87654321";
p.addr="abceddddd";
p.email="test2@eamil";
phoneDAODBImpl pi=new phoneDAODBImpl(MainActivity.this);
pi.addOne(p);
phone p1=pi.getOne(3);
 
Log.d("p1","p1"+p1.addr);
 
}
 
 

 

 

文章標籤

muchone 發表在 痞客邦 留言(0) 人氣()