昨天跟顧問討論著公司開發平台從下sql到寫Linq的各種心得
不禁有感而發
當初剛接觸Entity Framework和Linq時(公司則是用Telerik公司的DataAccess)
因為對IEnumerable和IQueryable的認知不清吃了不少效能上的悶虧
這兩樣東西的差別在於
IEnumerable :已執行Linq條件而產生的SQL,並將資料儲存在記憶體裡
IQueryable : 是一個指令的集合體,並沒有真的執行向資料庫取資料的動作
這一篇的重點應該就只有這兩句了
那到底該用哪個?這問題真是很難回答
只能看運用時機自己應變
舉個小例子
寫法一
var data = (from m in context.Members
join tm in context.TeamMembers
on m.MemberID equals tm.MemberID
join t in context.Teams
on tm.TeamID equals t.TeamID
where m.MemberID == memberid
select new { m, tm, t}).ToList();
foreach (var team in teamList)
{
var m = data.tm.Where(c => c.tm.TeamID==team).First();
//Do Something
}
寫法二
var data = (from m in context.Members
join tm in context.TeamMembers
on m.MemberID equals tm.MemberID
join t in context.Teams
on tm.TeamID equals t.TeamID
where m.MemberID == memberid
select new { m, tm, t});
foreach (var team in teamList)
{
var m = data.tm.Where(c => c.tm.TeamID==team).First();
//Do Something
}
大家來找碴
兩段程式的差別只在於寫法一多了一個ToList()
但背後實際執行起來卻大有差異
寫法一是在loop外面執行一次取資料
loop裡面的where都是針對記憶體裡的List在做處理
寫法二則是loop裡面每一個where才去跟資料庫要一次資料
還是如同前面所說的
哪一個比較好真的要看情況
真的不知道哪個好,那就兩種都跑跑看比較performance吧!!
2016年1月29日 星期五
2015年12月22日 星期二
關於OpenQuery帶參數的兩三事
前言
最近由於公司oracle主機更新
DBA盯長運算的sql盯得特別緊
於是幾個sql server上的古蹟就被挖出來了
也發現了幾個有趣的現象跟大家分享一下
最開始收到DBA傳來的sql是長這樣的
(雖然我覺得table schema算不上機密,但還是改編了一下)
select * from tableA where FLAG<>'Y' and NAME<> 'xxx'
這個tableA裡面包含了日期欄位
每天都有資料進帳,也就是說他是一個不算小的龐大table
看到這句sql不由得驚呼「怎麼會這樣子寫SQL!?」
追查了一下sql server上面的寫法後發現
在sql server上是這麼寫的
insert temptable
SELECT * FROM OPENQUERY(oracle_con, 'select * from tableA') AS a
WHERE FLAG <> 'Y' AND NAME <> 'xxx' AND ID IS NOT NULL
and SDATE>@sdate
這樣的一句指令
在我本來的認知中他去了oracle應該就只有select * from tableA這段而已
有趣的他卻帶了兩個where條件過去,這有點顛覆了我對openquery的認知
不過更有趣的是,最後一個條件是帶參數過去不不意外
但為什麼ID IS NOT NULL這條件也過不去呢?
恩,雖然有趣但這神秘的規則就待以後再慢慢研究了
今天主要想提的是openquery的寫法
正確來說openquery該執行的應該是
select * from tableA' WHERE FLAG <> 'Y' AND NAME <> 'xxx' AND ID IS NOT NULL
and SDATE>@sdate
這樣的完整句子才能避免不必要的資源浪費並縮短執行時間
我們來改造一下這段
首先是openquery帶參數的部分
第一段
先來組sql字串吧
DECLARE @TSQL nvarchar(4000)
SELECT @TSQL = 'SELECT * FROM OPENQUERY(oracle_con, ''select * from tableA WHERE FLAG <> ''''Y'''' AND NAME <> ''''xxx'''' AND ID IS NOT NULL
and SDATE>'''''+@sdate+''''' '') AS a '
接著執行
EXEC sp_executesql @TSQL
就有資料了~~~
咦?不對,我們是要insert到temptable裡我要怎麼把executesql裡面的東西拿出來呢!?
傻瓜,包進去就對了
DECLARE @TSQL nvarchar(4000)
SELECT @TSQL = ' insert temptable
SELECT * FROM OPENQUERY(oracle_con, ''select * from tableA WHERE FLAG <> ''''Y'''' AND NAME <> ''''xxx'''' AND ID IS NOT NULL
and SDATE>'+@sdate+' '') AS a'
EXEC sp_executesql @TSQL
稍微說一下因為在nvarchar裡,一個'要變兩個'
然後openquery裡面的因為是字串裡的字串,所以兩個'要再變成四個'
總之就是很多個點
這裡隱藏了一個亮點
「為什麼你的SDATE沒有點!!!不對他是oracle的話你就算點了也沒用」
恩......不瞞您說.....SDATE這欄位.....是個NUMBER.......
如果真的要帶日期的參數.....Convert這麼好用自己轉一轉再用字串去帶吧!!
最近由於公司oracle主機更新
DBA盯長運算的sql盯得特別緊
於是幾個sql server上的古蹟就被挖出來了
也發現了幾個有趣的現象跟大家分享一下
最開始收到DBA傳來的sql是長這樣的
(雖然我覺得table schema算不上機密,但還是改編了一下)
select * from tableA where FLAG<>'Y' and NAME<> 'xxx'
這個tableA裡面包含了日期欄位
每天都有資料進帳,也就是說他是一個不算小的龐大table
看到這句sql不由得驚呼「怎麼會這樣子寫SQL!?」
追查了一下sql server上面的寫法後發現
在sql server上是這麼寫的
insert temptable
SELECT * FROM OPENQUERY(oracle_con, 'select * from tableA') AS a
WHERE FLAG <> 'Y' AND NAME <> 'xxx' AND ID IS NOT NULL
and SDATE>@sdate
這樣的一句指令
在我本來的認知中他去了oracle應該就只有select * from tableA這段而已
有趣的他卻帶了兩個where條件過去,這有點顛覆了我對openquery的認知
不過更有趣的是,最後一個條件是帶參數過去不不意外
但為什麼ID IS NOT NULL這條件也過不去呢?
恩,雖然有趣但這神秘的規則就待以後再慢慢研究了
今天主要想提的是openquery的寫法
正確來說openquery該執行的應該是
select * from tableA' WHERE FLAG <> 'Y' AND NAME <> 'xxx' AND ID IS NOT NULL
and SDATE>@sdate
這樣的完整句子才能避免不必要的資源浪費並縮短執行時間
我們來改造一下這段
首先是openquery帶參數的部分
第一段
先來組sql字串吧
DECLARE @TSQL nvarchar(4000)
SELECT @TSQL = 'SELECT * FROM OPENQUERY(oracle_con, ''select * from tableA WHERE FLAG <> ''''Y'''' AND NAME <> ''''xxx'''' AND ID IS NOT NULL
and SDATE>'''''+@sdate+''''' '') AS a '
接著執行
EXEC sp_executesql @TSQL
就有資料了~~~
咦?不對,我們是要insert到temptable裡我要怎麼把executesql裡面的東西拿出來呢!?
傻瓜,包進去就對了
DECLARE @TSQL nvarchar(4000)
SELECT @TSQL = ' insert temptable
SELECT * FROM OPENQUERY(oracle_con, ''select * from tableA WHERE FLAG <> ''''Y'''' AND NAME <> ''''xxx'''' AND ID IS NOT NULL
and SDATE>'+@sdate+' '') AS a'
EXEC sp_executesql @TSQL
稍微說一下因為在nvarchar裡,一個'要變兩個'
然後openquery裡面的因為是字串裡的字串,所以兩個'要再變成四個'
總之就是很多個點
這裡隱藏了一個亮點
「為什麼你的SDATE沒有點!!!不對他是oracle的話你就算點了也沒用」
恩......不瞞您說.....SDATE這欄位.....是個NUMBER.......
如果真的要帶日期的參數.....Convert這麼好用自己轉一轉再用字串去帶吧!!
2015年4月21日 星期二
[C#]老師,外部執行檔不理我
這篇文章的出現是有歷史共業在的
隨著時光飛逝科技進步
一間公司經營久了系統多了人也老了
便開始出現了所謂的"舊系統"跟"新系統"
舊系統只要還堪用也舉不出什麼致命的缺陷
在人力資源不足的狀況下往往就會讓他繼續活下去
而新系統開發時在資源再利用的思維模式作祟下
就會有引用舊系統功能的需求出現
"寫成一個service大家用阿"
傻瓜,連dll都拿不到了還指望service
最後各退一步就是呼叫你的執行檔給你參數你output資料給我
賀,前言說了這麼多開始進入正題
協調好資料交換的格式之後,得到了一個精美的exe執行檔
裡面做什麼事你完全不知道,他會給你什麼結果你也無法預期
會跳error已經是很好的狀況了
最糟的是他什麼都不給你就一直hang住
同理心,執行檔會hang住肯定是出現了什麼他也沒預料到的特殊狀況才這樣
天助自助者,我們自己給的timeout設定不就得了
一般來說C#呼叫執行檔取output你會這麼寫
string ret = string.Empty;
using (Process proc = new Process())
{
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.CreateNoWindow = true;
proc.StartInfo.RedirectStandardOutput = true;
//塞入你的參數
proc.StartInfo.Arguments = parameter;
//你的執行檔
proc.StartInfo.FileName = exeFile;
proc.Start();
ret = proc.StandardOutput.ReadToEnd();
proc.WaitForExit();
}
在各種無法預期的不可抗力下
你很有機會在ReadToEnd()那邊等上一輩子
設定timeout的寫法
string ret = string.Empty;
using (Process proc = new Process())
{
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.CreateNoWindow = true;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.Arguments = parameter;
proc.StartInfo.FileName = exeFile;
StringBuilder output = new StringBuilder();
using (AutoResetEvent outputWaitHandle = new AutoResetEvent(false))
{
proc.OutputDataReceived += (sender, e) =>
{
if (e.Data == null)
{
outputWaitHandle.Set();
}
else
{
output.AppendLine(e.Data);
}
};
proc.Start();
proc.BeginOutputReadLine();
//人生苦短不該花費在等待上,設定一個timeout的秒數吧
int waitTimeSecond = 20;
if (proc.WaitForExit(waitTimeSecond * 1000) &&
outputWaitHandle.WaitOne(waitTimeSecond * 1000)
{
ret = output.ToString();
}
// Timed out.
else
{
ret = "老師,外部執行檔不理我";
}
}
}
隨著時光飛逝科技進步
一間公司經營久了系統多了人也老了
便開始出現了所謂的"舊系統"跟"新系統"
舊系統只要還堪用也舉不出什麼致命的缺陷
在人力資源不足的狀況下往往就會讓他繼續活下去
而新系統開發時在資源再利用的思維模式作祟下
就會有引用舊系統功能的需求出現
"寫成一個service大家用阿"
傻瓜,連dll都拿不到了還指望service
最後各退一步就是呼叫你的執行檔給你參數你output資料給我
賀,前言說了這麼多開始進入正題
協調好資料交換的格式之後,得到了一個精美的exe執行檔
裡面做什麼事你完全不知道,他會給你什麼結果你也無法預期
會跳error已經是很好的狀況了
最糟的是他什麼都不給你就一直hang住
同理心,執行檔會hang住肯定是出現了什麼他也沒預料到的特殊狀況才這樣
天助自助者,我們自己給的timeout設定不就得了
一般來說C#呼叫執行檔取output你會這麼寫
string ret = string.Empty;
using (Process proc = new Process())
{
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.CreateNoWindow = true;
proc.StartInfo.RedirectStandardOutput = true;
//塞入你的參數
proc.StartInfo.Arguments = parameter;
//你的執行檔
proc.StartInfo.FileName = exeFile;
proc.Start();
ret = proc.StandardOutput.ReadToEnd();
proc.WaitForExit();
}
在各種無法預期的不可抗力下
你很有機會在ReadToEnd()那邊等上一輩子
設定timeout的寫法
string ret = string.Empty;
using (Process proc = new Process())
{
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.CreateNoWindow = true;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.Arguments = parameter;
proc.StartInfo.FileName = exeFile;
StringBuilder output = new StringBuilder();
using (AutoResetEvent outputWaitHandle = new AutoResetEvent(false))
{
proc.OutputDataReceived += (sender, e) =>
{
if (e.Data == null)
{
outputWaitHandle.Set();
}
else
{
output.AppendLine(e.Data);
}
};
proc.Start();
proc.BeginOutputReadLine();
//人生苦短不該花費在等待上,設定一個timeout的秒數吧
int waitTimeSecond = 20;
if (proc.WaitForExit(waitTimeSecond * 1000) &&
outputWaitHandle.WaitOne(waitTimeSecond * 1000)
{
ret = output.ToString();
}
// Timed out.
else
{
ret = "老師,外部執行檔不理我";
}
}
}
2013年8月28日 星期三
[ios]縮你的鍵盤
作為一個xcode的新手,筆者今天卡在一個畫面相當久
诶........不好意思,請問我該怎麼關掉這個鍵盤
起初我一直認為一定是我沒用過iphone跟他不熟不會操作
抑或是模擬器少了什麼鈕可以按
尋尋覓覓了許久....我放棄,還是請出google大神吧
不料在01上看到了這麼一篇
WTF!!?只是要關閉一個鍵盤居然得使用密技!?
同時在搜尋結果中看到了一個"Cxxxa輕鬆收起你的iPhone鍵盤"的app
連這種app都出現了,我更加確定的相信這個結論........
iPhone的鍵盤沒有讓你收起它的地方!!!
好吧,介面上辦不到,我從程式裡動手總行吧
接下來才是今天的重點
怎麼收鍵盤?
其實只是很簡單的一個method
[self.tbTime resignFirstResponder];
tbTime是我的TextField
我有兩個TextField可能造成這個鬼擋牆的鍵盤
所以就是
[self.tbLength resignFirstResponder];
[self.tbTime resignFirstResponder];
不用特別去判斷TextField是否有focus,沒有focus呼叫這method也不會怎樣
接著就是觸發的時機點了
搜尋鈕的Click事件是一定要的,事件裡複製貼上就好了
接著額外衍生的問題來了
大部分查到的做法都是利用背景Click的時候來縮鍵盤
但我整個畫面都被MapView佔領了,背景就那麼一點點
且MapView沒有Click事件可以用耶
這時就要靠UITapGestureRecognizer這東西了
先直接奉上程式
- (void)viewDidLoad
{
[super viewDidLoad];
UITapGestureRecognizer *tgr = [[UITapGestureRecognizer alloc]
initWithTarget:self action:@selector(handleGesture:)];
tgr.numberOfTapsRequired = 1;
[self.myMap addGestureRecognizer:tgr];
[self refreshLocationData];
}
這段是說,我在load的時候宣告了一個UITapGestureRecognizer
handleGesture做的事情如下
- (void)handleGesture:(UIGestureRecognizer *)gestureRecognizer
{
[self.tbLength resignFirstResponder];
[self.tbTime resignFirstResponder];
}
就是剛剛隱藏鍵盤的那兩行啦
接著指定這個tgr觸發的tap次數,我們希望點一下就縮鍵盤,所以是1
最後再將tgr新增到MapView中就大功告成啦!!
诶........不好意思,請問我該怎麼關掉這個鍵盤
起初我一直認為一定是我沒用過iphone跟他不熟不會操作
抑或是模擬器少了什麼鈕可以按
尋尋覓覓了許久....我放棄,還是請出google大神吧
不料在01上看到了這麼一篇
WTF!!?只是要關閉一個鍵盤居然得使用密技!?
同時在搜尋結果中看到了一個"Cxxxa輕鬆收起你的iPhone鍵盤"的app
連這種app都出現了,我更加確定的相信這個結論........
iPhone的鍵盤沒有讓你收起它的地方!!!
好吧,介面上辦不到,我從程式裡動手總行吧
接下來才是今天的重點
怎麼收鍵盤?
其實只是很簡單的一個method
[self.tbTime resignFirstResponder];
tbTime是我的TextField
我有兩個TextField可能造成這個鬼擋牆的鍵盤
所以就是
[self.tbLength resignFirstResponder];
[self.tbTime resignFirstResponder];
不用特別去判斷TextField是否有focus,沒有focus呼叫這method也不會怎樣
接著就是觸發的時機點了
搜尋鈕的Click事件是一定要的,事件裡複製貼上就好了
接著額外衍生的問題來了
大部分查到的做法都是利用背景Click的時候來縮鍵盤
但我整個畫面都被MapView佔領了,背景就那麼一點點
且MapView沒有Click事件可以用耶
這時就要靠UITapGestureRecognizer這東西了
先直接奉上程式
- (void)viewDidLoad
{
[super viewDidLoad];
UITapGestureRecognizer *tgr = [[UITapGestureRecognizer alloc]
initWithTarget:self action:@selector(handleGesture:)];
tgr.numberOfTapsRequired = 1;
[self.myMap addGestureRecognizer:tgr];
[self refreshLocationData];
}
這段是說,我在load的時候宣告了一個UITapGestureRecognizer
handleGesture做的事情如下
- (void)handleGesture:(UIGestureRecognizer *)gestureRecognizer
{
[self.tbLength resignFirstResponder];
[self.tbTime resignFirstResponder];
}
就是剛剛隱藏鍵盤的那兩行啦
接著指定這個tgr觸發的tap次數,我們希望點一下就縮鍵盤,所以是1
最後再將tgr新增到MapView中就大功告成啦!!
2013年8月20日 星期二
[ios]iOS6 程式設計實戰 - 136個快速上手的開發技巧
非常不愛看書的我
今天要來推薦一本工具書
碁峯的iOS6 程式設計實戰 - 136個快速上手的開發技巧
在開始介紹這本書之前,首先必須告知
這本書並不是一本程式語言的教學
所以他不會從Objective-C的基礎開始教起
僅有在一開始稍微介紹了這語言的特色與需要注意的部分而已
而Objective-C的語法教學在網路上有相當多的資源可以學習
所以我們也不需要買一本從頭到尾都在說語法的書
筆者選書第一件事一定是看目錄
如果目錄的章節看起來就是
第一章 背景介紹
第二章 開發介面介紹
第三章 變數型態
第四章 迴圈與判斷式
這種書我會毫不考慮地放回書架上略過
因為每本書都長這樣,網路上找來的資源也都長這樣
那你該如何說服我買你呢?
回到這本書的目錄
如圖中所示
每一章介紹的是一個技術功能
書中一開始便告訴你,不建議你把這本書從第一頁開始看到最後一頁
因為有些東西你並不需要
但你可以把每個章節的標題掃過一次
當你開始開發一個app時,你會碰到各式各樣的功能需要實現
你需要開始尋找Objective-C以及iOS能幫你做什麼
這時再回到目錄來,翻到你需要的章節,取得你想學的東西
章節內的介紹我只能說是符合我的喜好
未必是適合大家
每個段落個一開始先簡單介紹過本段落的主要功能
並告知應先讀過哪些章節
接著的重頭戲,他將整個實作過程以條列式方式一步一步寫出
並明確說明每個動作應該寫在哪個地方
條列式最棒了!
你可以無腦的完全照著打過一次
再依照個人需求來做調整、修改
筆者學生時從來沒當過程式作業的源頭
因此拿別人的程式來改這件事完全就是我的style
當然,也不是多厚的一本書
當中一定會有一些變化的應用沒有完全說明
但有了基本用法以後,相信你一定可以在google上面以關鍵字找到更多變化
有明確的步驟以及修改即可完成的半成品
開發app這檔事,請容許我報告,完全沒有問題!!
書本資訊
書名:iOS6程式設計實戰 136個快速上手的開發技巧
出版社:碁峯
作者:朱克剛
定價:480 (p購物可以找到79折)
今天要來推薦一本工具書
碁峯的iOS6 程式設計實戰 - 136個快速上手的開發技巧
在開始介紹這本書之前,首先必須告知
這本書並不是一本程式語言的教學
所以他不會從Objective-C的基礎開始教起
僅有在一開始稍微介紹了這語言的特色與需要注意的部分而已
而Objective-C的語法教學在網路上有相當多的資源可以學習
所以我們也不需要買一本從頭到尾都在說語法的書
筆者選書第一件事一定是看目錄
如果目錄的章節看起來就是
第一章 背景介紹
第二章 開發介面介紹
第三章 變數型態
第四章 迴圈與判斷式
這種書我會毫不考慮地放回書架上略過
因為每本書都長這樣,網路上找來的資源也都長這樣
那你該如何說服我買你呢?
回到這本書的目錄
如圖中所示
每一章介紹的是一個技術功能
書中一開始便告訴你,不建議你把這本書從第一頁開始看到最後一頁
因為有些東西你並不需要
但你可以把每個章節的標題掃過一次
當你開始開發一個app時,你會碰到各式各樣的功能需要實現
你需要開始尋找Objective-C以及iOS能幫你做什麼
這時再回到目錄來,翻到你需要的章節,取得你想學的東西
章節內的介紹我只能說是符合我的喜好
未必是適合大家
每個段落個一開始先簡單介紹過本段落的主要功能
並告知應先讀過哪些章節
接著的重頭戲,他將整個實作過程以條列式方式一步一步寫出
並明確說明每個動作應該寫在哪個地方
條列式最棒了!
你可以無腦的完全照著打過一次
再依照個人需求來做調整、修改
筆者學生時從來沒當過程式作業的源頭
因此拿別人的程式來改這件事完全就是我的style
當然,也不是多厚的一本書
當中一定會有一些變化的應用沒有完全說明
但有了基本用法以後,相信你一定可以在google上面以關鍵字找到更多變化
有明確的步驟以及修改即可完成的半成品
開發app這檔事,請容許我報告,完全沒有問題!!
書本資訊
書名:iOS6程式設計實戰 136個快速上手的開發技巧
出版社:碁峯
作者:朱克剛
定價:480 (p購物可以找到79折)
2013年6月28日 星期五
[android]特別企劃~垃圾車在哪裡,絕對難不倒你
某個月黑風高的夜裡
筆者因為錯過了家門口的垃圾車
拿著手機連上環保局,看著沒有支援手機板的網站
痛苦的查著只有地址的垃圾車班表
不熟悉的路名還要貼到google map去找
提著一包垃圾騎著歐兜賣
在不斷的等待與錯過中就這樣在路上折騰了好久
最後才將垃圾交給一台偶遇的垃圾車結束這一天的冒險
有鑑於此
我發願要把這一切簡單化
筆者跟java不熟,也從來沒寫過任何app
但我相信google威能,於是就開始訂定了我需要的api和資料
更新,1跟2的資料
以高雄市來說,現在可以直接下載到垃圾車的座標資訊
https://waste.ksepb.gov.tw/
使用上方便太多了
/*
1. 垃圾車地點、時間資料
萬事起頭難,我決定第一步先不碰java
先用自己熟悉的C#來準備好需要的資料
雖然是用熟悉的技術
但這個是讓我搞了最久的部分
http://abandoned.kbj.com.tw/waste/search <--垃圾車資料網站
自己摸著摸著挖出了用QueryString來列所有資料的方式
http://abandoned.kbj.com.tw/waste/search/0/0/0/0/0 這是我最後找到的
最後一個參數是決定開始顯示的index
而每次固定顯示15筆,於是只能for loop了
這個處理資料的過程就不贅述了
基本上就是用HttpWebRequest抓畫面中的表格分析資料塞進sqlite
而各地環保局的網站各自成一格
若要將這功能發揚光大至全台灣恐怕花最多時間的都是在蒐集資料這工作了
2. 補足定位點資料
現在有了地址我打算連同座標也整理好才放進app
app做的事情只有讀出座標判斷距離顯示在地圖上
這邊使用的是google map的api
var url = String.Format("http://maps.googleapis.com/maps/api/geocode/xml?sensor=false&address={0}", address);
address帶的當然就是地址了
當中xml是我選比較習慣的格式,也可以用json的格式取得回傳結果
另外sensor這個參數一定要帶,不然查不出來
取出的xml分析的動作用XmlDocument就可以搞定了
格式及用法可參考 https://developers.google.com/maps/documentation/geocoding/?hl=zh-tw
另外google map這個api有每天2500次Query的限制
每秒內的Query次數也有限制
因此我為了補足這些資料洗了好幾次ip
*/
3. 資料內嵌進app
準備好的資料要送進app內
這邊我參考的是這篇
http://www.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications/
作法完全照抄網頁上的方式
4. Google Maps Android API
基本上這個app要達到的目的就是在地圖上顯示自己的座標和附近的垃圾車座標
而我相信google map會是一個好選擇
設定及使用方式參考了這個
http://cheng-min-i-taiwan.blogspot.tw/2013/04/google-maps-android-api-v2-android.html
溫馨小提醒
在Google API Console要打開的是Google Maps Android API v2不是Google Maps API喔
筆者由於眼殘在這邊卡了一下
5. 取得定位點
GPS定位這個只是個小技巧
網路上的資源多如牛毛
但大部分都是做個Class來implements LocationListener
我是懶人所以我則是參考了這篇
http://zhuyonghui116.blog.hexun.com.tw/43948361_d.html
另外發現在requestLocationUpdates後他就隨著周期卯起來一直定了
然而我只有在開啟app和按下更新時想去跑一次
所以還有參考了這篇
http://hp.dewen.org/?p=576
結合以上的東西,這個app大致上算完成了
剩下的就是換個美美的圖再把exception修一修
畢竟是個不熟悉的開發工具跟語言
整個過程其實也花了不少時間
但這也證明了一件事
你可以不會寫程式也可以不會用IDE
但你一定要會用google search
筆者因為錯過了家門口的垃圾車
拿著手機連上環保局,看著沒有支援手機板的網站
痛苦的查著只有地址的垃圾車班表
不熟悉的路名還要貼到google map去找
提著一包垃圾騎著歐兜賣
在不斷的等待與錯過中就這樣在路上折騰了好久
最後才將垃圾交給一台偶遇的垃圾車結束這一天的冒險
有鑑於此
我發願要把這一切簡單化
筆者跟java不熟,也從來沒寫過任何app
但我相信google威能,於是就開始訂定了我需要的api和資料
更新,1跟2的資料
以高雄市來說,現在可以直接下載到垃圾車的座標資訊
https://waste.ksepb.gov.tw/
使用上方便太多了
/*
1. 垃圾車地點、時間資料
萬事起頭難,我決定第一步先不碰java
先用自己熟悉的C#來準備好需要的資料
雖然是用熟悉的技術
但這個是讓我搞了最久的部分
http://abandoned.kbj.com.tw/waste/search <--垃圾車資料網站
自己摸著摸著挖出了用QueryString來列所有資料的方式
http://abandoned.kbj.com.tw/waste/search/0/0/0/0/0 這是我最後找到的
最後一個參數是決定開始顯示的index
而每次固定顯示15筆,於是只能for loop了
這個處理資料的過程就不贅述了
基本上就是用HttpWebRequest抓畫面中的表格分析資料塞進sqlite
而各地環保局的網站各自成一格
若要將這功能發揚光大至全台灣恐怕花最多時間的都是在蒐集資料這工作了
2. 補足定位點資料
現在有了地址我打算連同座標也整理好才放進app
app做的事情只有讀出座標判斷距離顯示在地圖上
這邊使用的是google map的api
var url = String.Format("http://maps.googleapis.com/maps/api/geocode/xml?sensor=false&address={0}", address);
address帶的當然就是地址了
當中xml是我選比較習慣的格式,也可以用json的格式取得回傳結果
另外sensor這個參數一定要帶,不然查不出來
取出的xml分析的動作用XmlDocument就可以搞定了
格式及用法可參考 https://developers.google.com/maps/documentation/geocoding/?hl=zh-tw
另外google map這個api有每天2500次Query的限制
每秒內的Query次數也有限制
因此我為了補足這些資料洗了好幾次ip
*/
3. 資料內嵌進app
準備好的資料要送進app內
這邊我參考的是這篇
http://www.reigndesign.com/blog/using-your-own-sqlite-database-in-android-applications/
作法完全照抄網頁上的方式
4. Google Maps Android API
基本上這個app要達到的目的就是在地圖上顯示自己的座標和附近的垃圾車座標
而我相信google map會是一個好選擇
設定及使用方式參考了這個
http://cheng-min-i-taiwan.blogspot.tw/2013/04/google-maps-android-api-v2-android.html
溫馨小提醒
在Google API Console要打開的是Google Maps Android API v2不是Google Maps API喔
筆者由於眼殘在這邊卡了一下
5. 取得定位點
GPS定位這個只是個小技巧
網路上的資源多如牛毛
但大部分都是做個Class來implements LocationListener
我是懶人所以我則是參考了這篇
http://zhuyonghui116.blog.hexun.com.tw/43948361_d.html
另外發現在requestLocationUpdates後他就隨著周期卯起來一直定了
然而我只有在開啟app和按下更新時想去跑一次
所以還有參考了這篇
http://hp.dewen.org/?p=576
結合以上的東西,這個app大致上算完成了
剩下的就是換個美美的圖再把exception修一修
畢竟是個不熟悉的開發工具跟語言
整個過程其實也花了不少時間
但這也證明了一件事
你可以不會寫程式也可以不會用IDE
但你一定要會用google search
2012年9月4日 星期二
[VS]visual studio 2010 之 消失的scrollbar
雖然說vs2012都出了
安裝完也是用了很久的telerik web元件之後
不過小弟我最近才剛開始從vs2008轉到vs2010
題外話,雖然我的NB只是兩萬塊的便宜貨又沒有ssd
但i5開vs2010慢成這樣也著實令我驚訝
題外話,雖然我的NB只是兩萬塊的便宜貨又沒有ssd
但i5開vs2010慢成這樣也著實令我驚訝
安裝完也是用了很久的telerik web元件之後
遇到了神秘的狀況,我的toolbox的scroll bar消失了
用滾輪也滾不動,下面還卡了好幾個東西選不到
試了一下子之後發現了這個神祕的現象
不囉嗦直接看影片
一直展開項目開到一定程度之後scroll bar就會消失
同時可以發現的是scroll bar的拉bar小到一個程度以後就不再縮小
看起來是個故意設定的行為
理由為何就要問問微軟囉
訂閱:
文章 (Atom)