// === @ModelAttribute ===
@ReuestMapping(value=...)
public String m(
@ModelAttribute(ATTRIBUTE_MODEL) MyObject myObject) {
// 若 MyObject 前有宣告 @ModelAttribute(ATTRIBUTE_MODEL)
// 會受 prepare() 中對 MyObject o 操作的影響
// 若沒有宣告 則仍單純是 form bean
}
@ModelAttribute(ATTRIBUTE_MODEL)
public Object prepare() {
// 進入 m() 前會先經過這裡
MyObject o = new MyObject();
return o;
}
// === URL Mapping ===
@RequestMapping(value = URL_MAPPING, method = RequestMethod.POST)
public String m(
@RequestParam(value = ATTRIBUTE_ID, required = true) BigDecimal id) {
// 除了 RequestMapping 中的 value 要 mapping 到以外
// 若 RequestParam 中 required = true,request 中也必須帶有此 attribute
}
// === Mapping enum object to DB ===
// DB 內儲存的是 NAME1
// @Enumerated 便會儲存 MyObject 所對應的 name
@Enumerated (EnumType.STRING)
public MyObject getMyObject() {}
enum MyObject {
NAME1("value1");
}
// DB 內儲存的是 DB_VALUE
// 從 DB 取出後 可藉 valueOfCode 取得相對應 MyObject
enum MyObject {
NAME1("DB_VALUE");
private static volatile Map<String, MyObject> registry = new HashMap<String, MyObject>();
// Use DB_VALUE be the key of Map
// put value to Map and use key to get MyObject
public static MyObject valueOfCode (String code) {
if(0 == registry.size()) {
synchronized ( registry) {
if(0 == registry.size()) {
for(MyObject o: MyObject.values()) {
registry.put(o. code, o);
}
}
}
}
return registry.get(code);
}
}
2012年7月1日 星期日
[Spring] Mapping among jsp, controller and DB
[Apache] Directory setting
httpd.conf
Alias /virtualUrl /RealUrlAllowOverride None Options None Order allow,deny Allow from all
2012年6月30日 星期六
[Spring] Spring Expression Language (SpEL)
Assume get this value from DB #{#root["valueB"]}/path
* Reference
- Spring Expression Language (SpEL)
// Using Expression parser, valueB should be found from DB, too.
Expression expression = parser.parseExpression(property.getValue(),
new TemplateParserContext());
property.setValue(expression.getValue(context, String.class));
* Reference
- Spring Expression Language (SpEL)
2012年6月22日 星期五
[Web] Brief notes
- slf4j
- 在 jar 檔時就 binding,比較好切換。
- framework
- 提供 pattern 的模組
- Spring framework
- 本身是個大 factory,將工作交給底下的 factory...
- Struts2
- #attribute 作用約是 ${attribute}
- iBatis
- $var$
- paraClass 中的 attribute
- #fieldName:fieldType#
- Table field
- HTML
- 由上而下 compiler,結果會是 DOM tree 結構。
- DTD
- 描述 HTML syntax
- <meta>
- 提供和 browser or search engine 相關的訊息。
- ex: 描述文檔的內容。
2012年6月15日 星期五
[Android] Context
public abstract class Context
getApplicationContext()
* Reference
- 求getApplicationContext用法-Android 问题&解答-eoeAndroid开发者社区 - Powered by Discuz!
- 谈谈Android里的Context的使用!!! - Android_Tutor的专栏 - 博客频道 - CSDN.NET
- 管理 global application 資訊的 interface,是由 Android System 實作。
- Interface to global information about an application environment. This is an abstract class whose implementation is provided by the Android system.
- 可由此取得 application-specific 的 resources and classes。
- It allows access to application-specific resources and classes, as well as up-calls for application-level operations such as launching activities, broadcasting and receiving intents, etc.
getApplicationContext()
- 在啟動 app 時,預設會啟動 Application,也就是 AndroidManifest.xml 中的 <application>,因此也能自己實作指定在此 tag 中,替代此預設。
- 回傳所在 process 中的 global application context。
- Return the context of the single, global Application object of the current process.
- 應被使用在當 lifecycle 不和當前 component 綁在一起時。
- This generally should only be used if you need a Context whose lifecycle is separate from the current context, that is tied to the lifetime of the process rather than the current component.
- registerReceiver(BroadcastReceiver, IntentFilter)
- 如果使用的是 Activity context,這個 receiver 就是被註冊在此 Activity,所以你必須在此 Activity destroy 前 unregister 此 receiver,若沒有這樣做則會發生 exception。
- If you use the Activity context to register a receiver that is static (global to the process, not associated with an Activity instance) then that registration will be removed on you at whatever point the activity you used is destroyed.
- 如果是使用 Application context,這個 receiver 是和 application 相關連,因此不會被 unregistered,但有可能會造成 leak。
- However using the ApplicationContext elsewhere can easily lead to serious leaks if you forget to unregister, unbind, etc.
- 使用在 DB 操作時。
* Reference
- 求getApplicationContext用法-Android 问题&解答-eoeAndroid开发者社区 - Powered by Discuz!
- 谈谈Android里的Context的使用!!! - Android_Tutor的专栏 - 博客频道 - CSDN.NET
[JPA] @OneToMany
// ObjectA many-to-one with ObjectB
// In ObjectA
// mappedBy 的值是在 ObjectB 中的 attribute
@OneToMany(fetch = FetchType.LAZY, mappedBy = "objectA")
public List<ObjectB> getObjectB() {
return objectBs;
}
// In ObjectB
@ManyToOne(fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST, CascadeType.MERGE })
@JoinColumns({
@JoinColumn(name = "FIELD_X", referencedColumnName = "FIELD_X", insertable = false, updatable = false )
})
public ObjectA getObjectA() { return objectA; }
[Database] BigDecimal
當 table 對應為物件時
若其 value 長度可能會超過 java int
這時候就會使用 BigDecimal type
ex: 流水號
* Reference
- How big is BigDecimal?
若其 value 長度可能會超過 java int
這時候就會使用 BigDecimal type
ex: 流水號
* Reference
- How big is BigDecimal?
[Graphic] Gif format
GIF 的版本有分
不會動的一定是 87a 格式
或是可以使用 Ultra Edit 查看 header
可分辨是何種格式的
* Reference
- wiki GIF
- GIF 87a: 不會動的
- GIF 89a: 此版本的格式才支援動態
不會動的一定是 87a 格式
或是可以使用 Ultra Edit 查看 header
可分辨是何種格式的
* Reference
- wiki GIF
[AndroidLayout] Inflate layout
Error Message
06-11 16:31:59.046: E/ListView(28360): at java.lang.reflect.Method.invoke(Method.java:507)
06-11 16:31:59.046: E/ListView(28360): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:849)
06-11 16:31:59.046: E/ListView(28360): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:607)
06-11 16:31:59.046: E/ListView(28360): at dalvik.system.NativeStart.main(Native Method)
Solution
inflate layout 傳入參數為
inflate(R.layout.items_row, parent, false);
or
inflate(R.layout.items_row, null);
* Reference
- Android: Custom ListAdapter extending BaseAdapter crashes on application launch
06-11 16:31:59.046: E/ListView(28360): at java.lang.reflect.Method.invoke(Method.java:507)
06-11 16:31:59.046: E/ListView(28360): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:849)
06-11 16:31:59.046: E/ListView(28360): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:607)
06-11 16:31:59.046: E/ListView(28360): at dalvik.system.NativeStart.main(Native Method)
Solution
inflate layout 傳入參數為
inflate(R.layout.items_row, parent, false);
or
inflate(R.layout.items_row, null);
* Reference
- Android: Custom ListAdapter extending BaseAdapter crashes on application launch
2012年6月9日 星期六
[Android] Content Provider
- Content providers are the standard interface that connects data in one process with code running in another process.
- The provider and provider client automatically handle security and inter-process communication.
ContentResolver
- In the client application's process.
- Owns the provider automatically handle inter-process communication.
- Acts as an abstraction layer between its repository of data and the external appearance of data as tables.
query(Uri, projection, selection, selectionArgs, sortOrder)
Should do queries asynchronously on a separate thread. (ex: CursorLoader class)
- projection: the columns that will be returned for each row
- The expression that specifies the rows to retrieve is split into a selection clause and selection arguments.
- selection:
- The selection clause is a combination of logical and Boolean expressions, column names, and values (the variablemSelection).
- selection 中的值應用 ? 取代,實際的值放在 selectionArgs(the selection arguments array ),作為對應.
- The selection clause is set to null, and the query returns all the words in the provider
Query result:
- If no rows match the selection criteria
- Cursor.getCount() is 0 (an empty cursor).
- If an internal error occurs
- Return null, or it may throw an Exception.
- Since a Cursor is a "list" of rows, a good way to display the contents of a Cursor is to link it to a ListView via a SimpleCursorAdapter.
Content providers can offer the following formats:
You can see the available data types by looking at the Cursor class "get" methods.
- integer
- long integer (long)
- floating point
- long floating point (double)
- Binary Large OBject (BLOB) implemented as a 64KB byte array
Three alternative forms of provider access are important in application development:
- Batch access:
- You can create a batch of access calls with methods in the ContentProviderOperation class, and then apply them with ContentResolver.applyBatch().
- Useful for:
- Inserting a large number of rows.
- Inserting rows in multiple tables in the same method call
- Performing a set of operations across process boundaries as a transaction (an atomic operation).
- Asynchronous queries:
- You should do queries in a separate thread.
- One way to do this is to use a CursorLoader object. The examples in the Loaders guide demonstrate how to do this.
- Data access via intents:
- Although you can't send an intent directly to a provider, you can send an intent to the provider's application, which is usually the best-equipped to modify the provider's data.
* Reference
- Content Providers
- Content Provider Basics
2012年6月3日 星期日
[Database] DataSource
有下列管理 transaction 的方式:
連至 DB 的方式:
If web service is on Server:
If NOT:
- JDBC
- JTA
- 管理的範圍較廣,可以包含多種不同來源。
- DataSource
連至 DB 的方式:
- Local -> server -> DB
- 要透過 jndi 向 server 取得 look up service -> DATASOURCE。
- Too dependent on server.
- Local -> DB
- Security issue(user, password).
If web service is on Server:
- 可以直接對應 jndi 取得 Datasource。
If NOT:
- 方式一: 利用 InitialContext,預設會使用 jndi.properties 中的 jndi name。
public class DataSourceFactory {
private static DataSource dataSource;
public static synchronized DataSource getDataSource()
throws ConnectionException, NamingException {
if (dataSource != null) {
return dataSource;
}
String datasourceJndiName = Configuration.getInstance().getJndiName();
if (datasourceJndiName == null) {
throw new ConnectionException("cann't find datasource jndi name!");
}
InitialContext ctx = new InitialContext();
DataSource ds = (DataSource) ctx.lookup("java:comp/env/" + datasourceJndiName);
dataSource = ds;
return dataSource;
}
}
- 方式二: springframework configuration, 透過 org.springframework.jndi.JndiObjectFactoryBean。
- 此設定是 spring 包裝 方式一 取得 datasource 的過程。
- 在這裡可以自行指定 jndi 變數來源。
- 若是沒有此設定,則如 方式一 預設使用 jndi.properties 中的設定,因此若沒有在此檔中提供此資訊會掛掉。
[Android] WebView WebViewClient
- WebViewClient.onLoadResource
- Anything loaded in webview will pass by.
- WebViewClient.shouldOverrideUrlLoading
- Actions occured in webview will pass by.
- But! Standard links and server redirects trigger shouldOverrideUrlLoading(); window.location does not.
2012年6月2日 星期六
[AndroidProcess] Background works
Main thread 負責處理 UI event,所以也稱為 UI thread,Activity、Service、Receiver、Provider,都是由 main thread 負責執行。因此不能在此 thread 中執行耗時的動作,android 會發出 ANR,這時候就得在 background thread 中執行,讓 main thread 同時仍能回應或執行 UI event,以避免 ANR 狀況。
sendBroadcast() 與 startService() 都一樣會被丟到 main message queue 裡,等待 main thread 的執行,只有呼叫 local content provider 不會進到 main message queue 裡,而是由 main thread 直接執行。但如果是 remote content provider 則是由 thread pool 中取得 thread 來執行,外部 client 呼叫 service 也是如此。
每個 Thread 中都有 Looper 和 Message Queue,Message Queue 中儲存著要被處理的 events (UI event and System event),Looper 負責 Thread 和 Message Queue 間的連繫。
另外,因為是 main thread 負責更新 UI,所以若是試圖在 worker thread 中更新 UI,是會得到 exception 的,必須把更新 UI 的動作再丟給 main thread 處理。
可選擇以下方式:
* Simple Worker Thread and runOnUiThread()/View.post()
View.post()
Each View object has a message queue which is processed sequentially on the UI thread. post() allows us to add a new message to the message queue.
* new Thread + Handler
Handler: 負責處理 thread 的訊息(message)。
* AsyncTask
** AsyncTask and Handler
* Loader
* Service
* IntentService extends Service
* Pending
* Reference
- Background Tasks – Part 1 (Introduction)
- Background Tasks – Part 2 (Worker thread, Handler)
- Background Tasks – Part 3 (AsyncTask)
- Background Tasks – Part 4 (Loader)
- Background Tasks – Part 5 (Service)
- Background Tasks – Part 6 (IntentService)
- Android之Service与IntentService的比较 - HiPhoneZhu的专栏 - 博客频道 - CSDN.NET **
- 深入研究 IntentService 原始碼 ***
- IntentService的功用
- Android Handler 筆記 **
- Java Artisan: Android AsyncTask 與 Handler Thread 的差異 **
- Java Artisan: 在 Android 裡使用 Local Service
sendBroadcast() 與 startService() 都一樣會被丟到 main message queue 裡,等待 main thread 的執行,只有呼叫 local content provider 不會進到 main message queue 裡,而是由 main thread 直接執行。但如果是 remote content provider 則是由 thread pool 中取得 thread 來執行,外部 client 呼叫 service 也是如此。
每個 Thread 中都有 Looper 和 Message Queue,Message Queue 中儲存著要被處理的 events (UI event and System event),Looper 負責 Thread 和 Message Queue 間的連繫。
另外,因為是 main thread 負責更新 UI,所以若是試圖在 worker thread 中更新 UI,是會得到 exception 的,必須把更新 UI 的動作再丟給 main thread 處理。
可選擇以下方式:
* Simple Worker Thread and runOnUiThread()/View.post()
View.post()
Each View object has a message queue which is processed sequentially on the UI thread. post() allows us to add a new message to the message queue.
new Thread(new Runnable() {
@Override
public void run() {
// TODO works here.
runOnUiThread(new Runnable() {
@Override
public void run() {
// UI event
}
});
// or
final TextView textView =
(TextView) findViewById( R.id.textview );
textView.post(new Runnable() {
@Override
public void run() {
// UI event
textView.setText( "Hello World" );
}
});
}
}).start();
* new Thread + Handler
Handler: 負責處理 thread 的訊息(message)。
private Handler handler = new Handler() {
@Override
public void handleMessage(android.os.Message msg) {
// UI event
progressDialog.dismiss();
};
}
new Thread() {new Runnable() {
@Override
public void run() {
// TODO works here.
// 把 message 送給 handler 處理。
handler.sendEmptyMessage(0);
// or 將 Runnable post 到 handler。
handler.post(new Runnable() {
@Override
public void run() {
textView.setText( "Hello World" );
}
});
}
}.start();
* AsyncTask
- 如果只會 Override doInBackground 則可考慮使用 Thread 即可。
- AsyncTask 會 hold Activity context 直到工作結束,所以可能會有 context leak 問題。
new AsyncTask() { // onPreExecute(), onProgressUpdate() @Override protected Void doInBackground(Void... params) { // TODO works here. return null; } @Override protected void onPostExecute(Void result) { // UI event }; }.execute();
** AsyncTask and Handler
- AsyncTask 內部實做機制為較新且較強的 java.util.concurrent,但較佔資源,而 Handler Thread 則為基本的 Java Thread。
- 由於 Handler Thread 依靠 Message Queue 與 Main Thread 互動,相對於 AsyncTask,Handler Thread 比較可能發生塞車情況。
- 但 Handler Thread 在即時互動上優於 AsyncTask,因為 Main Thread 可以隨時傳送 Message 給 Handler Thread,而 AsyncTask 不行,只能依照事先定義 Callback 進行。
- 基於輕量環境資源的有限,當執行單一的工作時建議使用 AsyncTask,如下載一個大檔案,但是當執行大量重複性的工作時,建議使用 Handler Thread,如下載多個小圖。
* Loader
- Introduced in Android 3.0 and also included in the Support Library.
- Used to asynchronously load data in an activity or fragment.
- Quite effectively to perform these tasks:
- Loading content either from a SQLite database or file storage, or from a network resource as a background task.
- There are essentially three components that we need:
- LoaderManager
- Manages one or more Loader instances.
- Loader
- The actual workhorse that will perform your background task.
- LoaderManager.LoaderCallbacks
- An interface that you need to implement to manage the lifecycle of the Loader
- How to use:
- Obtain LoaderManager instance from Activity/Fragment/FragmentActivity.
- Implement LoaderManager.LoaderCallbacks.
- Will create a loader.
- Get called when the loader either finishes, or is reset.
- These will all be executed on the UI thread, and we will typically implement them within our Activity / FragmentActivity.
- 也就是在 Loader 中處理 UI event。(?)
* Service
- Services is a means of performing some task which is not attached to a specific Activity.
- Run in the main thread of their hosting process. (並不會在另一個 thread 中執行,所以不適做耗費 CPU 的工作 會有 ANR 的可能,或者是必須 new a thread。)
- There are two types of Service:
- A background Service
- The default type of Service and can be killed by the OS (or Task Killer apps, more of them later) to free up system resources.
- A foreground service
- Not be killed by the OS, but requires an ongoing Notification to be displayed in the Notification bar while it is running so that the user is aware that the foreground Service is active and will not be killed automatically by the OS.
- ex: music player.
* IntentService extends Service
- Service + Handler + HandlerThread。
- Will receive a single Intent and then shut down automatically once we have processed it.
- 和 Service 不同,此 api 會執行在自己的 worker thread,陸續執行交給它的 request,但只會有一個 worker thread 同時也只會執行一個 request,當執行完後會自行停止。
- 實做其 onHandleIntent(Intent intent),在這裡處理 request。
- 是設計用來可以在一個 Service 中服務多項工作,因此在 onHandleIntent(),不可以呼叫 stopSelf(),全部工作結束,它會自行停止。
- start service -> send message to handler that has non-UI thread looper -> handlerMessage() -> onHandleIntent()
- Looper 就是訊息迴圈 (message loop),這是 Android UI 在處理各式訊息時,最重要的元件之一。
- One word of warning:
- Performing long tasks in an IntentService does have the inherent risk that it will stop if the device goes to sleep. You can prevent this from happening by holding a WakeLock while onHandleIntent() is executing. Just make sure you release it before onHandleIntent() returns. Alternatively use Mark Murphy’s WakefulIntentServicepattern.
* Pending
- StrictMode
- API level 9。
- 可用於發現潛在問題,ex: 你該使用 background thread 的動作。
- Loader
- API level 11。
* Reference
- Background Tasks – Part 1 (Introduction)
- Background Tasks – Part 2 (Worker thread, Handler)
- Background Tasks – Part 3 (AsyncTask)
- Background Tasks – Part 4 (Loader)
- Background Tasks – Part 5 (Service)
- Background Tasks – Part 6 (IntentService)
- Android之Service与IntentService的比较 - HiPhoneZhu的专栏 - 博客频道 - CSDN.NET **
- 深入研究 IntentService 原始碼 ***
- IntentService的功用
- Android Handler 筆記 **
- Java Artisan: Android AsyncTask 與 Handler Thread 的差異 **
- Java Artisan: 在 Android 裡使用 Local Service
2012年5月20日 星期日
[AndroidDev] Managing the Activity Lifecycle
- 如果 AndroidManifest.xml 中沒有任何 activity 有宣告 MAIN action 與 LAUNCHER category,此 app 的 launch icon 則不會出現在 app list 中。
- onPause <-> onResume
- onStop -> onRestart -> onStart -> onResume
onCreate()
- 適合處理在整個 activity life 中只應處理一次的邏輯,ex: 初始化 class-scope variables。
onRestart()
- 當 activity 是從 onStop() 被啟動時,系統才會呼叫此 method。所以若是有在 onStop() 中釋放資源,記得在此初始或設定。
onStart()
- activity 已為可見狀態,但會很快的便進入 onResume()。
onResume()
- 會停留到 resume 完 activity 到暫停前的狀態。
onPause()
- activity 仍為半可視狀態,ex: 被 dialog 覆蓋。
- 可表示 user 離開此 activity 而進入 onStop(),所以可執行:
- Stop animations or other ongoing actions that could consume CPU.
- Commit unsaved changes, but only if users expect such changes to be permanently saved when they leave (such as a draft email).
- Release system resources.
- broadcast receivers, handles to sensors (like GPS).
- Any resources that may affect battery life while your activity is paused and the user does not need them.
- 不需要在此儲存 user 所輸入的資料,因為其實此 Activity instance 還是被儲存在 memory 中的,所以當在 onResume(),元件的狀態會再被重新載入,除非這是項明確功能:
- ex: email 會自動儲存為草槁。
- 不適合在此中處理會耗費 CPU 的工作,ex: 寫入 DB,因為會拖慢顯現下一個 activity 的速度,所以這類型的工作更適合在 onStop() 中處理。
- 要到 activity B 前,activity A 需先進入 onPause()。
onStop()
- 保證 UI 不是可視的,user 已在使用另一個 activity 或 app。
- 適合做耗費 CPU 的工作:
- ex: 寫入 DB。
- 不需要在此儲存 user 所輸入的資料,因為其實此 Activity instance 還是被儲存在 memory 中的,所以當 onResume(),元件的狀態會再被重新載入。
- ex: If the user entered text into an EditText widget, that content is retained so you don't need to save and restore it.
- 即使 activity 被 destroy,其中的 View objects 仍會被儲存在 Bundle 中,並且在 user 回到此 activity(the same instance of the activity) 時被重新載入。
- 以下情況使得 activity A 會被 stopped 與 restarted:
- user 由 Recent Apps window 開啟另一個 app,activity A 會進入 onStop(),若 user 再由 Home launcher icon or Recent Apps window 開啟你的 app,那麼 activity A 會進入 onRestart()。
- 在你的 app 中進入下一個 activity,activity A 會進入 onStop(),若 user 按下 Back 鍵,activity A 會進入 onRestart()。
- user 在使用 app 時有來電。
onDestroy()
- The system calls onDestroy() after it has already called onPause() and onStop() in all situations except one:
- when you call finish() from within the onCreate() method.
- onCreate() 會直接進入 onDestroy()。
以下情況可能會使得你的 activity 被 destroyed:
- The user presses the Back button.
- Calling finish().
- Activity is in onStop() 且已長時間沒有被使用而被系統回收。
- Foreground activity 需要更多資源,因此關閉 background processes to recover memory。
若 activity 是被系統回收,那麼系統會記下它的狀態(is called the "instance state", stored in a Bundle object.),以在 user 想開啟此 activity 時能 restore 該狀態。
onSaveInstanceState()
- 當系統要 destroy this activity,會呼叫此 method,並且傳入 Bundle object 來儲存 activity 資訊,所以你若有需要保存的資訊也可儲存在此 Bundle 中。
- 然後此 activity 會被系統 recreate 並且傳入與 destroy 時相同的 Bundle object,因此可以在 onCreate() 中從 Bundle 中取出之前所儲存的資訊。
- 但因為 activity 可以是完全新建立或是重新被建立的,也就是說傳入的 Bundle 不一定都是有值的,若是要使用,務必判斷是不是 null。
- 或者與其在 onCreate() 中 restore 資訊,也可以選擇在 onRestoreInstanceState() 做。
- 此 method 會在 onStart() 後被呼叫。
- 只有在 Bundle != null 時會被呼叫。
- The default implementation of this method saves information about the state of the activity's view hierarchy:
- ex: he text in an EditTextwidget or the scroll position of a ListView.
- 所以在此 method 和 onRestoreInstanceState() 中記得呼叫 super.xxxx; 以儲存與重載 the state of the view hierarchy。
* Reference
- Starting an Activity | Android Developers
- Pausing and Resuming an Activity | Android Developers
- Stopping and Restarting an Activity | Android Developers
- Recreating an Activity | Android Developers
訂閱:
文章 (Atom)