我們常常會用 Graphics2D.drawString("Hello", 100, 100); 在元件上畫出字串,
若想要依字串畫出來的大小來決定其位置,可以先取得 FontMetrics 物件,
FontMetrics fm = getFontMetrics(font);
再透過 FontMetrics.getHeight() 和 fm.stringWidth(String) 即可拿到該字串的高和寬。
2013年3月29日 星期五
Static variables are not resetting when the application is destroyed
當 APP 觸發 OnDestory() 而結束時,所宣告的 static variables 並不會因此而重設,
必須手動重設,這是因為當 class 被載入時,靜態變數就會一直存在直到 class
被卸載,像是 Remove 整個 APP 時或系統記憶體不足的時候。
必須手動重設,這是因為當 class 被載入時,靜態變數就會一直存在直到 class
被卸載,像是 Remove 整個 APP 時或系統記憶體不足的時候。
Do not use Socket with DataInputStream
今天在寫的 socket 程式時,使用 DataInputStream/DataOutputStream 來傳遞資料,
發現用 DataInputStream 時,能夠一次讀到的 bytes 很少,每次都是 1448 bytes
(不知道怎麼算出來的?),讀的也很慢。試著改用 BufferedInputStream/BufferedOutputStream
來傳遞資料發現變快許多,而且每次能讀的的 bytes 也比較多,都是 1448 的整數倍,
1448, 2896(2x1448), 4344(3), 8688(6), 30408(21), 33304(23), 36200(25)... 等。
發現用 DataInputStream 時,能夠一次讀到的 bytes 很少,每次都是 1448 bytes
(不知道怎麼算出來的?),讀的也很慢。試著改用 BufferedInputStream/BufferedOutputStream
來傳遞資料發現變快許多,而且每次能讀的的 bytes 也比較多,都是 1448 的整數倍,
1448, 2896(2x1448), 4344(3), 8688(6), 30408(21), 33304(23), 36200(25)... 等。
2013年3月28日 星期四
new Socket 時發生 Exception
今天想寫一個 Android 的 Client 端將資料傳輸到 PC 的 Server 端。
我在 onCreate() 時去 new Socket(strIP, 27015) 卻發生 NullPointerException。
strIP 明明就不是 null pointer,傳進去後卻莫名變成 null 了。
在網路上也找不到相關的資料,索性試著將 new Socket 一行移至 OnClick(),
這時跑出了另一個 NetworkOnMainThreadException,於是讓我找到了相關的文章。
根據 Why Ice Cream Sandwich Crashes Your App 這篇文章的說明,Android 3.0 以上
不允許在 UI thread 裡做以下的運算:
我在 onCreate() 時去 new Socket(strIP, 27015) 卻發生 NullPointerException。
strIP 明明就不是 null pointer,傳進去後卻莫名變成 null 了。
在網路上也找不到相關的資料,索性試著將 new Socket 一行移至 OnClick(),
這時跑出了另一個 NetworkOnMainThreadException,於是讓我找到了相關的文章。
根據 Why Ice Cream Sandwich Crashes Your App 這篇文章的說明,Android 3.0 以上
不允許在 UI thread 裡做以下的運算:
- Opening a Socket connection (i.e. new Socket()).
- HTTP requests (i.e. HTTPClient and HTTPUrlConnection).
- Attempting to connect to a remote MySQL database.
- Downloading a file (i.e. Downloader.downloadFile()).
Debugging with Android SDK source code
之前已提過 [Eclipse] 對 Java SDK source code debug。
對於 Android SDK source code debug 也是一樣,問題是要如何取得 Android SDK
的 source code 呢? 對於 Android 4.0 之前需要用 Repro 和 Git 這類的工具將 source
抓下來,到了 4.0 之後不需要在這麼麻煩,直接在 Android SDK Manager 就可以
下載,下載完後在 Debug perspective 對該 process 按下滑鼠右鍵選擇
Edit Lookup Path... 設置對應路徑即可。
對於 Android SDK source code debug 也是一樣,問題是要如何取得 Android SDK
的 source code 呢? 對於 Android 4.0 之前需要用 Repro 和 Git 這類的工具將 source
抓下來,到了 4.0 之後不需要在這麼麻煩,直接在 Android SDK Manager 就可以
下載,下載完後在 Debug perspective 對該 process 按下滑鼠右鍵選擇
Edit Lookup Path... 設置對應路徑即可。
▲ Android SDK Manager |
[Eclipse] 對 Java SDK source code debug
我們可以安裝 JRE 或 JDK 來開發 Java 程式,但若要看到 Java SDK 的 source code,
並針對其 Debug,我們就只能安裝 JDK 了。
只要在 Window → Preferences → Java → Installed JREs → Search.... 設置 JDK 所安裝的
路徑即可。如此一來便可透過 F3 或 Ctrl + 滑鼠左鍵看到定義 String 的 class 檔,而不會
有 "Source not found" 的訊息頁跑出來。
有 "Source not found" 的訊息頁跑出來。
2013年3月26日 星期二
Cursor 在 OnStop 完之後被 Reset 了?
今天在使用 Cursor 時發現,使用開發的 App 到一半關螢幕,
使其觸發 OnStop() 事件,在當下 c.getPosition() 的值還是對的,
OnRestart() 回來後,c.getPosition() 卻變成 -1,也就是被重新指回頭了。
不知道是預期的行為還是怎樣,只好用個變數在 OnStop() 時記下,
OnRestart() 回來後,在把 cursor 指向原來的位置。
使其觸發 OnStop() 事件,在當下 c.getPosition() 的值還是對的,
OnRestart() 回來後,c.getPosition() 卻變成 -1,也就是被重新指回頭了。
不知道是預期的行為還是怎樣,只好用個變數在 OnStop() 時記下,
OnRestart() 回來後,在把 cursor 指向原來的位置。
Macro # 和 ## 的用法
使用 # 可以把巨集引數變為一個字串,而 ## 則把兩個巨集引數串接在一起。
例如:
例如:
#define STR(s) #s #define EXP(a,b) int(a##e##b) printf ("Number %s\n", STR(655.3)); // Number 655.3 printf ("Number %s\n", EXP(5, 2)); // int(5e2), Number 500
2013年3月25日 星期一
讀取外部記憶體的圖片並秀在 ImageView 上
Step 1: 宣告外部記憶體 URI 位置
Uri uriMedia = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
Step 2: Query URI 的資料,利用 c.moveToNext() 取得繞行所有圖片的資料。
Cursor c = managedQuery(uriMedia, null, null, null, null);
Step 3: 取得 _id 後,建立該圖片完整的 URI。
uriSource = Uri.withAppendedPath(uirMedia, c.getString(0));
取得完整的 URI 後,有兩種方法可以秀出圖片:
Step 4.1: 利用 URI 的 stream data 建立 Bitmap 物件。
ContentResolver resolver = getContentResolver();
resolver.openInputStream(uriSource)
imageView.setImageBitmap(bitmap);
Step 4.2: 直接將 URI 當參數設給 imageView
imageView.setImageURI(uriSource);
在這邊要注意的是,Android 單一程式的記憶體空間只能使用到 16~128MB,所以當
圖片太大不管是 setImageBitmap 或 setImageURI,都有可能造成 Out of Memory 的
錯誤訊息。解決方法可見 Loading Large Bitmaps Efficiently。
Runtime.getRuntime().totalMemory() 可以查看應用程式目前的記憶體(Heap Size)大小,
Heap Size 是動態增長的。
Runtime.getRuntime().maxMemory() 可以查看應用程式的記憶體(Heap Size)能增長到多大。
Uri uriMedia = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
Step 2: Query URI 的資料,利用 c.moveToNext() 取得繞行所有圖片的資料。
Cursor c = managedQuery(uriMedia, null, null, null, null);
Step 3: 取得 _id 後,建立該圖片完整的 URI。
uriSource = Uri.withAppendedPath(uirMedia, c.getString(0));
取得完整的 URI 後,有兩種方法可以秀出圖片:
Step 4.1: 利用 URI 的 stream data 建立 Bitmap 物件。
ContentResolver resolver = getContentResolver();
resolver.openInputStream(uriSource)
imageView.setImageBitmap(bitmap);
Step 4.2: 直接將 URI 當參數設給 imageView
imageView.setImageURI(uriSource);
在這邊要注意的是,Android 單一程式的記憶體空間只能使用到 16~128MB,所以當
圖片太大不管是 setImageBitmap 或 setImageURI,都有可能造成 Out of Memory 的
錯誤訊息。解決方法可見 Loading Large Bitmaps Efficiently。
Runtime.getRuntime().totalMemory() 可以查看應用程式目前的記憶體(Heap Size)大小,
Heap Size 是動態增長的。
Runtime.getRuntime().maxMemory() 可以查看應用程式的記憶體(Heap Size)能增長到多大。
2013年3月5日 星期二
把常用的 TortoiseSVN 功能整合進 Visual Studio
我們可以將 TortoiseSVN 常用的功能,如 Log 和 Blame 整合進 Visual Studio,
步驟如下:
開啟 VS -> Tools -> External Tools...
Command: C:\Program Files\TortoiseSVN\bin\TortoiseProc.exe
Arguments(Log): /command:log /path:"$(ItemPath)"
Arguments(Blame): /command:blame /path:"$(ItemPath)" /line:$(CurLine)
如此一來,就可以在 VS 上對某一段 code 做 Log 和 Blame 啦! 相當好用!
步驟如下:
開啟 VS -> Tools -> External Tools...
[External Tools] |
Command: C:\Program Files\TortoiseSVN\bin\TortoiseProc.exe
Arguments(Log): /command:log /path:"$(ItemPath)"
Arguments(Blame): /command:blame /path:"$(ItemPath)" /line:$(CurLine)
如此一來,就可以在 VS 上對某一段 code 做 Log 和 Blame 啦! 相當好用!
2013年3月4日 星期一
利用指令透過 Visual Studio 開啟指定檔案
我們可以在執行檔 C:/Program Files/Microsoft Visual Studio 8/Common7/IDE/devenv.exe
後面加上:
A.cpp /command "Edit.Goto 200"
或是
/edit A.cpp
兩者的差異是,前者會開啟新的 VS 並可指定行號,後者會用已開啟的 VS 做為編輯器,
但無法指定行號。
[Notepad++] 開啟某文件並留在某一行
這對開啟程式碼文件頗實用,指令如下:
C:\Program Files\Notepad++\notepad++.exe C:\a.cpp -n200
即可開啟 a.cpp 這個檔案,並停留在 200 行的位置。
更多的 Command Line 可參考:
1. http://npp-community.tuxfamily.org/documentation/notepad-user-manual/command-line
2. http://sourceforge.net/apps/mediawiki/notepad-plus/index.php?title=Command_Line_Switches
C:\Program Files\Notepad++\notepad++.exe C:\a.cpp -n200
即可開啟 a.cpp 這個檔案,並停留在 200 行的位置。
更多的 Command Line 可參考:
1. http://npp-community.tuxfamily.org/documentation/notepad-user-manual/command-line
2. http://sourceforge.net/apps/mediawiki/notepad-plus/index.php?title=Command_Line_Switches
訂閱:
文章 (Atom)