2013年12月4日 星期三
grep + less with color
grep -R --color=always "search string" * | less -R
若只有--color的話預設為--color=auto,pipe with less使用的話不會有顏色
less -R才會翻譯顏色escape charactor
2013年11月26日 星期二
linux 使用swap memory
最近嘗試在aws ec2 上deploy 一個ror的project
但因為使用的是free trail instace所以memory很小,deploy的時候會噴cannot allocate memory
要切一塊disk空間作為swap memory以解決這個問題
首先先確認是否已經存在swap memory:
如果沒有會顯示如下
在確認沒有swap memory後檢查我們是否有足夠的硬碟空間,我們要做一塊512mb的swap memory所以要至少這麼多
開始建立swap memory
接著使用這個空間
不過只是這樣重開機的話會失去效用,所以要把這塊swap memory加入fstab(file system table)中
加入這行
記得把Swappiness設定為0, 這樣可以確保os只有在緊急的時候(例如不swap就噴out of memory)才做swap動作,增加效能
但因為使用的是free trail instace所以memory很小,deploy的時候會噴cannot allocate memory
要切一塊disk空間作為swap memory以解決這個問題
首先先確認是否已經存在swap memory:
sudo swapon -s
如果沒有會顯示如下
Filename Type Size Used Priority
在確認沒有swap memory後檢查我們是否有足夠的硬碟空間,我們要做一塊512mb的swap memory所以要至少這麼多
df -h Filesystem Size Used Avail Use% Mounted on /dev/xvda1 7.9G 3.5G 4.1G 47% / udev 288M 12K 288M 1% /dev tmpfs 119M 176K 118M 1% /run none 5.0M 0 5.0M 0% /run/lock none 296M 0 296M 0% /run/shm
開始建立swap memory
sudo dd if=/dev/zero of=/swapfile bs=1024 count=512k sudo mkswap /swapfile執行完會顯示
Setting up swapspace version 1, size = 262140 KiB no label, UUID=xxxxxxxxxxxxxxxxxxxxxxxxxxx
接著使用這個空間
sudo swapon /swapfile
不過只是這樣重開機的話會失去效用,所以要把這塊swap memory加入fstab(file system table)中
sudo vim /etc/fstab
加入這行
/swapfile none swap sw 0 0
記得把Swappiness設定為0, 這樣可以確保os只有在緊急的時候(例如不swap就噴out of memory)才做swap動作,增加效能
sudo su - echo 0 > /proc/sys/vm/swappiness exit
2013年11月11日 星期一
Android: 使用LightingColorFilter 來做使用image background的button的onClick特效
以往我在做用其他image為background的button的onClick特效時,都要準備好兩張image,
一張為按下去前,一張為按下去後,實為麻煩.
後來發現只要使用Android sdk內建的LightingColorFilter就可以用一張圖達到不錯的類似效果:
一張為按下去前,一張為按下去後,實為麻煩.
後來發現只要使用Android sdk內建的LightingColorFilter就可以用一張圖達到不錯的類似效果:
mTestBtn.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
if(event.getAction() ==MotionEvent.ACTION_DOWN)
v.getBackground().setColorFilter(new LightingColorFilter(0xFF999999, 0xFF000000));
else if(event.getAction() ==MotionEvent.ACTION_UP)
v.getBackground().clearColorFilter();
return false;
}
});
2013年11月5日 星期二
Android: 當資料庫越來越肥大 之 容易擴充的DB架構
使用這樣的寫法在修改或擴增database的時候可以比較舒服(我覺得啦XD)
不過如果只是要寫一個小小且不太會擴充的db那就先不需要這把牛刀了!
後面有完全沒有整理過(囧)的範例code,可能看code比較好懂.
此架構大致分為五個部分:
我是另外建立了一個application class來確保db在被任何activity使用前已經初始劃完成.
剩下的就讓code自己來解說吧XD
不過如果只是要寫一個小小且不太會擴充的db那就先不需要這把牛刀了!
後面有完全沒有整理過(囧)的範例code,可能看code比較好懂.
此架構大致分為五個部分:
DBHelper
- 這個就是一般在寫db的時候繼承SQLiteOpenHelper而來的class,這邊增加了一些function讓操作更便利一點.擔負起了依照schema來建立table、實際操作db等重責大任.
- 這個class是獨立於project的,可以直接貼到別的project.
DBSchema
- 掌握了整個db的架構,建立實體以後會喂给DBHelper的constructor吃.
- 這個class幾乎也獨立於不同project,除了要在變數定義的時候告知這個project中table的相關資訊.另外加入新的Table時也記得要在這裡增加定義.
DBTable
- 每一個table有自己專屬的class,所以加入新table的時候基本上不會動到舊的架構.
- 提供的method儘量不存取到自己以外的table.
- 提供存取自己table 的method给data provider使用.
Data Provider
- 扮演db的adapter角色,可以存取多個db並且將資料處理組合後以便使用.
- app的其他部分需要存取資料理當只會使用到Provider,不會直接使用DBTable.
- Provider理當是唯一會直接使用到DBTable的class.
- 可以視需求增加不同的data provider
Global initialization
因為DBHelper是採用singleton,所以用application context來做初始化.我是另外建立了一個application class來確保db在被任何activity使用前已經初始劃完成.
建立一個新的table步驟:
- 先建立一個table class.
- 去Schema中加入Table資訊.
- 接著就可以在data provider中使用這個table.
剩下的就讓code自己來解說吧XD
2013年10月16日 星期三
Android: 建立一個configure class當作參數以增加constructor的彈性
如果初始化一個class所需要設定的參數太多,會造成這個class的constructor過長,這個情況可以利用自定義一個config class作為參數給constructor吃來解決.
這樣做有幾個特點:
用法:
接下來介紹config class的實作,架構如下:
使用final qualifier有兩個用意
(ps2. final 變數除了在宣告的時候直接assign值外唯一的設定機會是在constructor中)
藉由Builder的幫助來建立fields為final的config class
config class的constructor吃一個Builder物件作為參數
這邊加上static是因為static inner class不用reference到outer class 的instance,才可以直接用以下方式建立:
大概就是這樣,最後附上一段之前寫的code作為範例
這樣做有幾個特點:
- 可以確保在物件建構前設定所有建構時所需要的資訊
- 統一參數設定時機
- config class中對於optional的參數可以有default值
- 設定參數時可以有很大的自由度不用依照constructor規定的參數順序.
- 不代表之後不能變動參數,還是可以加入function 如MyClass.setNewHeight()
用法:
//usage
//為何要使用Builder與其實作後面說明
MyClassConfig config = MyClassConfig.Builder()
.setHeight(100)
.setWidth(50)
.setXXX(...)
.setYYY(...)
.build();
MyClass mc = new MyClass(config);
//constructor
MyClass(MyClassConfig config)
{
this.height = config.height;
this.width = config.width;
//other initialization
...
}
接下來介紹config class的實作,架構如下:
public class MyClassConfig {
//1.config class fields
...
//2.config class constructor
...
//3.static inner builder class:
public static class Builder
{
// 3.1 builder fields
...
// 3.2 builder constructor
...
// 3.3 builder setter
...
// 3.4 build() function
...
} // end of builder
}//end of MyClassConfig
1. config class fields
//首先定義fields,使用final qualifier來確保config建構的時候要完成全部的設定
final int height;
final int width;
...
使用final qualifier有兩個用意
- 確保全部的設定在config建構的時候就會完成
- MyClass要可以直接存取這些fields所以不能是private但又不希望config建構後fields還會被更動
(ps2. final 變數除了在宣告的時候直接assign值外唯一的設定機會是在constructor中)
藉由Builder的幫助來建立fields為final的config class
2.config class constructor
config class的constructor吃一個Builder物件作為參數
public MyClassConfig(Builder pBuilder)
{
this.height = pBuilder.height;
this.width = pBuilder.width;
...
}
3.static inner builder class
這邊加上static是因為static inner class不用reference到outer class 的instance,才可以直接用以下方式建立:
new MyClassConfig.Builder();
最後是builder 的實作
public static class Builder{
//3.1 builder fields
private int height;
//可以在這邊設定default value,如果build過程中沒有被更改,default value會被assign到最後build出來的config class中
private int width = 100;
//3.2 builder constructor
//如果建立config的時候需要一些外部資訊可以當作builder constructor的參數傳入
public Builder(){};
//3.3 builder setter
//設定config參數的functions, 回傳自己是為了可以達到method chaining的效果
//i.e., builder.setHeight(100).setWidth(100).build();
public Builder setHeight(int h)
{
this.height = h;
return this;
}
public Builder setWidth(int w)
{
this.width = w;
return this;
}
//3.4 build function
//最後建立出config的function
public MyClassConfig build()
{
return new MyClassConfig(this);
}
}
大概就是這樣,最後附上一段之前寫的code作為範例
package itri.u9lab.towolf.ratiofixer;
public class RatioLayoutConfig {
final int virtualWidth;
final int virtualHeight;
final boolean isFullScreenMode;
/*
* constructor
*/
public RatioLayoutConfig(Builder pBuilder)
{
this.virtualHeight = pBuilder.virtualHeight;
this.virtualWidth = pBuilder.virtualWidth;
this.isFullScreenMode = pBuilder.isFullScreenMode;
}
/*
* config builder
*/
public static class Builder
{
private int virtualWidth = 768;
private int virtualHeight =1230;
boolean isFullScreenMode = false;
public Builder()
{
}
public Builder setVirtualSize(int pWidth,int pHeight)
{
virtualWidth = pWidth;
virtualHeight = pHeight;
return this;
}
public Builder setFullScreen(boolean mode)
{
isFullScreenMode = mode;
return this;
}
public RatioLayoutConfig build()
{
return new RatioLayoutConfig(this);
}
}//end of builder
public static RatioLayoutConfig getDefaultConfig()
{
return new Builder().setFullScreen(false).setVirtualSize(768, 1230).build();
}
}
2013年9月10日 星期二
iOS 自定義動態資料TableView (customized tableview) + 附加section header使用
此篇環境為iOS 5以上, 使用storyboard.
分為兩個部分,第一部分為基本的tableview,
第二部分加上section header.
使用table view 分成兩個步驟
一、設定stroy board
接下來幾個關鍵步驟!
4.在table view cell的attribute inspector中Identifier要設定一個名字,之後才能抓到這個cell layout,如下
5.在每一個table view cell的元件中的attribute inspector中tag欄位,設定一個號碼,之後才可以抓到這個元件,如下
6.最後在這個table對應到的view controller上面define一個IBOutlet,並且與table相連
至此story board上的設置已經完成
二、在view controller中加code
1. 在header file (.h)檔案中
採用UITableViewDelegate,UITableViewDataSource兩個protocol:
並且定義上面所提到的IBOutlet:
和一個存放資料的Array:
2.在implementation file(.m)檔案中
implement以下幾個dataSource protocol function
3.在改變tableData的資料後記得要呼叫
讓table view reload 顯示最新的資料內容, for example:
至此已經完成可以依據server回傳資料改變內容的TableView
一、在storyboard中另外加入:
1.加入另外一個table view cell並且設置好想要的section header ui,如下顯示日期黑色那塊.
2.和先前一樣在attribute inspector中設定table view cell 的 identifier 和其中元件的tag
二、在implement file(.m)中加入header 相關的delegate method:
1.設定section header的高度:
2.設定section header的內容:
這裡的tabelData變數與part 1中並不相同,
使用section header時的table data有多種實作方式,這邊採用一個section的array,一個array cell包含了一個section object,其中又包含了這個section中的cell的方式
part 1 中所實作的delegate method也要有所修改:
設定每個cell 內容的方法也要更改成:
分為兩個部分,第一部分為基本的tableview,
第二部分加上section header.
Part 1,基本table view
使用table view 分成兩個步驟
一、設定stroy board
- 首先拉一個TableView元件到view controller中
- 再拉一個table view cell元件到table view 中
- 在table view cell中放好想要的ui配置,如下圖
接下來幾個關鍵步驟!
4.在table view cell的attribute inspector中Identifier要設定一個名字,之後才能抓到這個cell layout,如下
5.在每一個table view cell的元件中的attribute inspector中tag欄位,設定一個號碼,之後才可以抓到這個元件,如下
6.最後在這個table對應到的view controller上面define一個IBOutlet,並且與table相連
至此story board上的設置已經完成
二、在view controller中加code
1. 在header file (.h)檔案中
採用UITableViewDelegate,UITableViewDataSource兩個protocol:
@interface YourViewController : UIViewController <UITableViewDelegate,UITableViewDataSource>並且定義上面所提到的IBOutlet:
@property (weak, nonatomic) IBOutlet UITableView *mTableView;和一個存放資料的Array:
NSMutableArray* tableData;
2.在implementation file(.m)檔案中
implement以下幾個dataSource protocol function
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [tableData count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = @"announceTableCell";
//使用在story board設定的identifier才會抓到story board中的table view cell layout
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
//如果已經存在則重複使用
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:simpleTableIdentifier];
}
YourDataType *data = [tableData objectAtIndex:indexPath.row];
//利用在story board中設定的tag取得table view cell中的特定component
UILabel *titleLabel = (UILabel*)[cell viewWithTag:1];
[titleLabel setText:data.title];
UILabel *contentLable = (UILabel*)[cell viewWithTag:2];
[contentLable setText:data.description];
return cell;
}
3.在改變tableData的資料後記得要呼叫
[self.mTableView reloadData];
讓table view reload 顯示最新的資料內容, for example:
//假設執行一個向server 進行http request的function,並且傳回一個array
[ServerApiCaller callApiWithSuccess:^(NSArray *result) {
tableData = result;
[self.mTableView reloadData];
} failure:^(NSError *error, id result) {
}];
至此已經完成可以依據server回傳資料改變內容的TableView
Part 2, 加上section header
一、在storyboard中另外加入:
1.加入另外一個table view cell並且設置好想要的section header ui,如下顯示日期黑色那塊.
2.和先前一樣在attribute inspector中設定table view cell 的 identifier 和其中元件的tag
二、在implement file(.m)中加入header 相關的delegate method:
1.設定section header的高度:
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 106;
}
2.設定section header的內容:
這裡的tabelData變數與part 1中並不相同,
使用section header時的table data有多種實作方式,這邊採用一個section的array,一個array cell包含了一個section object,其中又包含了這個section中的cell的方式
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
NSString * const headerID = @"announceTableHeader";
//同一般的cell,依據id取得section header的layout
UIView * headerView = [tableView dequeueReusableCellWithIdentifier:headerID];
if(headerView == nil)
{
headerView = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:headerID];
}
//設定layout內的ui內容
//注意:這邊的tableData跟YourDataType和Part 1中的並不相同,一個array cell包含了一個section object,其中又包含了這個section中的cell
YourDataType * data = [tableData objectAtIndex:section];
UILabel *weekDay = (UILabel*)[headerView viewWithTag:1];
[weekDay setText:[data getWeekDay]];
UILabel *monthDay = (UILabel*)[headerView viewWithTag:2];
[monthDay setText:[data getDay]];
UILabel *year = (UILabel*)[headerView viewWithTag:3];
[year setText:[data getYear]];
//設定上圖中的"th"位置
UILabel *th = (UILabel*)[headerView viewWithTag:4];
CGSize textSize = [[monthDay text] sizeWithFont:[monthDay font]];
CGFloat strikeWidth = textSize.width;
[th setFrame:CGRectMake(monthDay.frame.origin.x + strikeWidth, monthDay.frame.origin.x, monthDay.frame.size.width, monthDay.frame.size.height)];
return headerView;
}
part 1 中所實作的delegate method也要有所修改:
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
//getListSize拿到這個section下的data cell數量
return [[tableData objectAtIndex:section] getListSize];
}
設定每個cell 內容的方法也要更改成:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = @"announceTableCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:simpleTableIdentifier];
}
//先從tableData中用indexPath.section拿到section
YourDataType *data = [tableData objectAtIndex:indexPath.section];
//再從section中用indexPath.row拿到cell
UILabel *titleLabel = (UILabel*)[cell viewWithTag:1];
[titleLabel setText:[data getTitleWithIndex:indexPath.row]];
UILabel *contentLable = (UILabel*)[cell viewWithTag:2];
[contentLable setText:[data getDescriptionWithIndex:indexPath.row]];
return cell;
}
訂閱:
文章 (Atom)



