Wednesday, December 4, 2013

Java - Concurrent 1

Process và Thread

  • Trong lập trình concurrent có hai đối tượng thực thi cơ bản: process và thread. 
  • Thông thường một hệ thông máy có nhiều process và thread hoạt động. 
  • Thời gian xử lý cho một single cỏe được chia sẽ giữa các process thông qua một tính năng của OS được gọi là time slicing
Process
  • Một process chứa một môi trường thực thi.
  • Một process có đầy đủ, tập hợp cơ bản tài nguyên run-time riêng, mỗi process có bộ nhớ riêng
  • Process đồng nghĩa với programs và application
  • Để hỗ trợ giao tiếp giữa các process, hầu hết các hệ điều hành đều support Inter Process Communiacation(IPC) như là pipes và sockets
  • IPC không chi được dùng để giao tiếp giữa các process trong cùng một hệ thống và còn với các process ở hệ thống khác.
Thread
  • Đôi khi được gọi là lightweight process. 
  • Cả thread và process đều cung cấp một môi trường thực thi, nhưng khởi tạo một thread tốn ít tai nguyên hơn là khởi tạo process.
  • Thread tồn tại bên trong process, mỗi process có it nhất một thread.
  • Các thread chia sẻ tài nguyên của process, bao gồm memory và các tệp tin.
  • Mỗi ứng dụng java đều có một hoặc nhiều thread. Nhưng theo quan điểm lập trình viên bạn bắt đầu mới chỉ một thread được gọi là main thread. Thread này có khả năng tạo thêm nhiều thread

Friday, August 23, 2013

Canvas.save, Canvas.restore; Camera.save, Camera.restore



Android graphics package contains android.graphics.Canvas andandroid.graphics.Camera classes, both of which allow you to manipulate the “Modelview” transformation matrix, with the latter manipulating your drawing in “3D”.

Basically the ability to manipulate complex, hierarchical transformation is achieved by an(?) internal matrix stack with the top matrix being the current one in effect and the one that you are manipulating. All the transformations you are making on the current matrix are cumulative; so if you were just to manipulate the current matrix, it’s going to be a big pain to draw something like a car or a human figure which conceptually is assembled by different parts. Canvas.save()/Camera.save() is to push a matrix into the stack; the result is the transformation you’ve made is saved into the stack. Canvas.restore()/Camera.restore() is to discard the current transformation and go back to the last saved one and continue on it. So if you want to continue with some transformation you made a while ago, you should first save/push it into the stack first so that you can go back to it by restoring/popping it out from the stack. See the following pseudo code for how we go about drawing a drag race car with huge wheels:

//setup/clean up stuff
canvas.save(); // remember where we are since we’d like to go back to this original transformation later;
// move the front wheel to front left
// make it twice as big as the normal wheel
// draw front-left wheel in normal size
canvas.restore(); // go back to the identity matrix;
// move the front wheel to front right
// make it twice as big as the normal wheel
// draw front-right wheel in normal size
canvas.restore();
//… draw body
canvas.restore();
//… and other wheels…

The pattern is
  • If you want to go back to the current state in terms of transformation, you should remember where you are by calling Canvas.save() or Camera.save());
  • Transform the matrix (via Canvas or Camera methods such as Canvas.translate() and Camera.rotateY();
  • Do drawing;
  • Go back to the transformation state you remember in step 1 by calling Canvas.restore()/Camera.restore() if you want to continue from the transformation you left in step 1;
  • In theory, if you only have one matrix transformation saved in the stack, you can simply push it out by calling Canvas.restore()/Camera.restore() again and again. But in the real world (at least applying for cupcake and donut),  I’ve found I have to keep “saving” before each new transformation and “restoring” after it, even if I was “saving”/”restoring” an identity matrix. So this means you would normally call Canvas.save()/Camera.save() each time before a new transformation;
  • Transform the matrix;
  • Do drawing;
  • Canvas.restore()/Camera.restore();
To summarize (applying to android.graphics.Camera as well), you repeatedly do the following cycles:
  1. canvas.save();
  2. transform matrix;
  3. draw;
  4. canvas.restore();


Note that in android, #2 transformation should be coded before #3 drawing to make the drawing stick to the transformation. If you reverse 2/3, your drawing won’t be affected by the transformations that come after it. This is kinda “counter-intuitive” at least for me since you have always need to set your canvas in position before you paint but not the other way around.

Check out the “Red book” for “Manipulating the Matrix Stacks” to get a better understanding. And here is a sample code showing you how I draw the awesome Batmobile (Spiderman’s car) crawling on a skyscraper (use your imagination for the wall and other details as I am still polishing my drawing skill. Please hold on for the next episode!):
package com.mh.android.test;
import android.app.Activity;
import android.content.Context;
import android.graphics.Camera;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.View;
public class HelloAndroidAgain extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new MyTestView(this));
}
private static class MyTestView extends View {
public MyTestView(Context context) {
super(context);
setMinimumWidth(200);
setMinimumHeight(200);
//camera = new Camera();
}
private Camera camera = new Camera();
@Override
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
camera.save();
camera.rotateY(60f);
camera.applyToCanvas(canvas);
canvas.drawColor(Color.DKGRAY);
Paint paint = new Paint();
paint.setTextSize(24);
//front left wheel
canvas.save();
canvas.translate(50f, 50f);//xCtr, yCtr
paint.setColor(Color.GREEN);
canvas.drawCircle(0, 0, 30, paint);
paint.setColor(Color.WHITE);
canvas.drawText(“FL”, -10, 10, paint);//string
canvas.restore();
//front right wheel
canvas.save();
canvas.translate(150f, 50f);
paint.setColor(Color.GREEN);
canvas.drawCircle(0, 0, 30, paint);
paint.setColor(Color.WHITE);
canvas.drawText(“FR”, -10, 10, paint);
canvas.restore();
//rear left wheel
canvas.save();
canvas.translate(50f, 150f);
paint.setColor(Color.GREEN);
canvas.drawCircle(0, 0, 30, paint);
paint.setColor(Color.WHITE);
canvas.drawText(“BL”, -10, 10, paint);
canvas.restore();
//rear right wheel
canvas.save();
canvas.translate(150f, 150f);
paint.setColor(Color.GREEN);
canvas.drawCircle(0, 0, 30, paint);
paint.setColor(Color.WHITE);
canvas.drawText(“BR”, -10, 10, paint);
canvas.restore();
//body
canvas.save();
canvas.translate(100f, 100f);
paint.setColor(Color.RED);
canvas.drawRect(-50, -50, 50, 50, paint);
canvas.restore();
camera.restore();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(getSuggestedMinimumWidth(), getSuggestedMinimumHeight());
}
}
}

source: http://maohao.wordpress.com/2009/09/30/canvas-save-canvas-restore/

Wednesday, June 26, 2013

Kiến trúc RCP


  1. Eclipse dựa trên các ứng dụng
    • một Eclipse application chứa các thành phần software độc lập
    • OSGi miêu tả phương pháp tiếp cần một mô-đun cho ứng dụng Java.
    • Equiox là một implementation của OSGi được sử dụng bởi Eclipse platform. Equinox runtime cung cấp framework cần thiết để chạy một mô-đun Eclipse application
    • SWT là thành phần thư viện UI cơ bản được sử dụng bởi Eclipse. JFace cung cấp một vài tiện ích APIs bên trên của SWT.
    • Workbench cung cấp framework cho ứng dụng, chịu trách nhiệm hiện thị tất cả các thành phần UI
  2. Thuật ngữ học
    • Một Eclipse application bao gồm một vài thành phần Eclipse
    • Một thành phần software trong Eclipse được gọi là plug-in
    • Một thành phần software trong OSGi được gọi là bundle
  3. Các file cấu hình quan trọng
    • MANIFEST.MF - Chứa các thông tin cấu hình của OSGi
    • plugin.xml - Bao gồm thông tin về các cơ chế mở rộng của Eclipse
    • Một Eclipse plug-in định nghĩa API của nó thông qua MANIFEST.MF
    • File plugin.xml cung cấp khả năng để định nghĩa extension và extension point. Extension point định nghĩa các interface cho các plug-in khác đóng góp các functionality. Extension đóng góp functionality cho interface của chúng. Functionatily có thể là code hoặc không dựa trên code.
  4. Các thành phần UI quan trọng
    1. Window
      • Eclipse application bao gồm một hoặc nhiều window, thông thường một ứng dụng chỉ có một window nhưng bạn không bị giới hạn việc này. Ví dụ nếu bạn muốn support multiple display cho hai monitors.
    2. Part
      • Là một thành phần UI cho phép người dùng điều hướng và chỉnh sửa dữ liệu. Thông thường các Part được chia thành các View và Editor.
      • View thông thường được sử dụng để làm việc trên một tập dữ liệu cái mà có thể là một cấu trúc phân cấp. Nếu dữ liệu bị thay đổi thông qua View, sự thay đổi này có hiệu lực trực tiếp tới cấu trúc dữ liệu bên dưới. Một View đôi khi cho phép chúng ta mở một Editor để chọn các tập dữ liệu.
      • Editor được sử dụng để chỉnh sửa một thành phần dữ liệu đơn. Để áp dụng sự thay đổi dữ liệu tạo ra bỏi editor, người dùng phải lưu nội dung của Editor một cách rõ ràng(vd: bấm nút save)
    3. Perspective
      • Perspective là một visual container cho một tập các Part. Eclipse application sử dụng Perspective để sắp xếp các Part cho các nhiệm vụ phát triển khác nhau
      • Bạn có thể thay đổi layout và content trong một Perspective bằng cách open hoặc close các Part hoặc sắp xếp lại chúng.
    4. PartStack và PartSashContainer
      • PartStack và PartSashContainer được sử dụng để gom nhóm và sắp xếp các Part.
      • PartStack chứa một stack của các Part, trong đó chỉ có một Part được hiện thị tại một thời điểm và có thể được chọn thông qua các Tabs.
      • PartSashContainer hiển thị tất cả children tại cùng thời điểm theo hàng ngang hoặc dọc.

Wednesday, June 19, 2013

NIO - SelectionKey

Một biểu tượng đại diện cho sự đăng kí của SelectableChannel với một selector.

Một selection key được khởi tạo mỗi khi một channel được đăng kí với một selector. Một key vẫn còn hợp lệ tới khi nó bị hủy bỏ bằng cách gọi hàm cancel của chính key đó hoặc đóng channel hoặc đóng selector. Hủy bỏ một key không xóa ngay nó khỏi selector của nó mà nó được thêm vào cancelled-key set của selector đó và nó bị loại bỏ trong suốt lần lựa chọn tiếp theo. Tính hợp lệ của key có thể kiểm tra bằng phương thức isValid.

Một selection key chứa 2 operation set được đại diện bởi một giá trị integer.  Mỗi bit của một operation set biểu thị một loại của selectable operation mà được hỗ trợ bỏi channel của key.

  • Interest set xác định các loại hành động nào sẽ được kiểm tra sự sẵn sàng vào lần tiếp theo khi phương thức lựa chọn của selector được gọi. Interest set được khởi tạo với giá trị nhận được khi key được tạo,  sau đó nó có thể thay đổi thông qua phương thức interestOps(int).
  • Ready set đinh nghĩa các loại hành động cho key's channel nào được phát hiện đã sẵn sàng bởi key's selector. Ready set được khởi tạo với giá tri 0 khi key được khởi tạo, sau đó nó có thể cập nhật bới selector trong suốt một selection operation, nhưng nó không thể cập nhật trực tiếp.
Một selection key's ready set chỉ ra rằng channel của nó sẵn sàng cho một vài loại hoạt động như một gợi ý, nhưng không đảm bảo, một hoạt động trong một loại có thể thực thi bởi một thread mà không bị block. Một ready set chính xác ngay lập tức sau khi hoàn thành hoạt động lựa chọn. Nó có thể được thực hiên không chính xác bởi các sự kiện bên ngoài và bới các hoạt đông I/O mà được gọi trên kênh tương ứng

Lớp này định nghĩa tất cả bit operation-set được biết,  nhưng chính xác bit nào được hỗ trợ bởi một channel dựa trên loại channel. Mỗi subclass của SelectableChannel định nghĩa một phương thức validOps() cái mà trả về một set xác định nhưng hoạt động mà được hỗ trợ bởi channel. Việc kiểm tra hoặc thiết lập  một operation-set bit là không được hỗ trợ bỏi key's channel sẽ trả về một runtime exception phù hợp.

Liên kết một vài dữ liệu application-specific với một selection key là cần thiết, ví dụ một đối tượng mà đại diện cho trạng thai của một protocol cấp cao và xử lý các readiness notification trong trật tự để implement protocol đó. Do đó selection key hỗ trợ attachment một object tùy ý cho một key. Một đối tượng có thể được gắn vào thông qua phương thức attach và sau đó nhận lại đối tương này thông qua phương thức attachment.

Selection keys an toàn khi sử dụng bởi nhiều thread cùng lúc. Các hoạt động đọc và ghi interest set sẽ được đồng bộ với các hoạt động của selector.




NIO - Selector

Một selector được khởi tạo bằng cách gọi hàm open của class này. Một selector mở tới khi nó bị đóng bằng cách gọi phương thức close.

Sự đăng kí của một selectable channel với một selector được đại diện bởi một đối tượng SelectionKey. Một selector duy trì 3 set của selection key:


  • Key set bao gồm các key đại diện các registration channel hiện tại của selector. Set này được trả về bởi phương thưc keys
  • Selected-key set là một tập hợp của các key mà mỗi channel của key được phát hiện là đã sẵn sàng cho it nhất một trong các hoạt động được định nghĩa trong tập hợp interest của key trong suốt một hoạt động lựa chọn trước đó. Set này được trả về bởi phương thức selectedKeys. selected-key set là subset của key set.
  • The cancelled-key set là một tập các key mà đã bị hủy bỏ nhưng các channel vẫn chưa hoàn toàn deregister. Không thể truy xuất trực tiếp set này. Là subset của key set.
Cả 3 set đều rỗng khi mới được khởi tạo.

Một key được thêm vào key set của selector như một tác dụng phụ của việc đăng kí channel thông qua phương thức register của channel. Các key bị hủy bỏ được xóa khỏi keyset strong suốt các hoặt động lựa chọn. Key set không có khả năng sử đổi trực tiếp.

Một key được thêm vào cancelled-key set khi nó bị hủy bỏ bằng cách đóng channel của nó hoặc gọi phương thức cancel. Việc hủy bỏ một key sẽ khiên channel bị deregister trong suốt hoạt động lựa chọn tiếp theo, tại thời điểm đó key sẽ bị xóa khỏi key set của selector.

Các key được thêm vào selected-key set bởi các hoạt động lựa chọn. Một key có thể bị xóa trực tiếp từ selected-key set bằng cách gọi phương thức remove của set hoặc phương thức remove của một interator thu  được từ set

Selection

Trong môi selection operation các key có thể được thêm vào và xóa bỏ từ một selected-key set của selector và có thể bị xóa khỏi key set và cancelled-key set của nó. Selection được thực thi bỏi select(), select(long) và selectNow() method. Liên quan tới 3 bước:
  1. Mỗi key trong cancelled-key set bị xóa bỏ khỏi từng key set của cái mà nó là thành viên và channel của nó bị deregister. Bước này cancelled-key set rỗng.
  2. underlying operating system được truy vấn cho một update về sự sẵn sàng của mỗi channel còn lại để thực thi bất kỳ các hoạt động được định nghĩa bởi key's interest set của nó như tại thời điểm mà selection operation bắt đầu.Cho một channel mà sẵn sàng cho ít nhất một hoạt động, một trong 2 action sau sẽ được thực thi:
    • Nếu key của channel không có sẵn trong selected-key set thì nó được thêm vào, và ready-operation set của nó được chỉnh sửa để xác định chính xác những hoạt động cho cái mà channel báo cáo để sẵng sàng ngay bây giờ. Bất kì thông tin sẵng sàng ghi lại trước đó trong ready set bị hủy bỏ.
    • Mặt khác key của channel đã có sẵn trong selected-key set, vì vậy ready-operation set của nó được sửa đổi để xác định bất kì hoạt động mới cho cái mà channel được báo cáo để sẵn sàng. bất kỳ thông tin sẵn sàng được ghi lại trước đó trong ready set được duy trì
  3. Nếu tất cả key được thêm vào cancelled-key set trong khi bước 2 đang trong quá trình thì chúng được xử lý như trong bước 1.

NIO - SelecableChannel

Một channel có thể ghép kênh thông qua một Selector

Trong trình tự để được sử dụng với một selector, một thể hiện của class này trước tiên phải được đăng kí thông qua register method. Method này trả về một đối tương SelectionKey mới đại diện cho sự đăng kí với selector.

Khi đã đăng kí với selector, một channel được duy trì tới khi nó bị hủy bỏ. Điều này liên quan tới deallocating  bất cứ tài nguyên nào được cấp phát cho channel bởi selector.

Một channel không thể bị deregister trực tiếp. thay vào đó key đại diện cho sự đăng kí của nó phải bị hủy bỏ. Hủy bỏ một key tức là channel bị deregister trong suốt hoạt động lựa chọn tiếp theo của selector. Key có thể bị hủy bỏ bằng cách gọi phương thức cancel của nó. Tất cả key của channel sẽ bị hủy bỏ ngầm nếu channel bị đóng.

Nếu selector bị đóng thì channel sẽ bị deregister, và key đại diện cho sự đăng kí sẽ không hợp lệ.

Một channel có thể được đăng kí nhiều selector riêng biệt

Kiểm tra channel được đăng kí hay chưa ta sử dụng phương thức isRegistered

Các Selectable channel an toàn khí sử dụng nhiều thread cùng lúc.

Blocking mode
Một selectable channel có 2 chế độ: blocking hoặc non-blocking. Trong chế độ blocking mọi hoạt động I/O được gọi trên channel sẽ bị block tới khi nó hoàn thành. Trong chế độ non-blocking một hoạt động I/O sẽ không bị block và có thể truyền số byte ít hơn số byte được yêu cầu hoặc có thể không truyền byte nào. Chế độ blocking của selectable channel có thể xác định bởi phương thức isBlocking.

Khi mới khởi tạo selectable channel trong chế độ blocking. Non-blocking rất hữu dụng trong việc kết hợp với selector-based multiplexing. Một channel phải được đặt trong chế độ non-blocking mode trước khi đăng kí với một selector, mà có thể không trở về được chế độ blocking cho tới khi no bị deregister.

NIO - Channels Package

Đại diên cho các kết nói tới thực thể mà có khả năng thực thi các hoạt động I/O như file, socket, định nghĩa ra selector cho phép multiplexed (ghép kênh), non-blocking I/O operations.


  • Channel: một mối quan hệ cho I/O operations
    • ReadableByteChannel: có thể đọc vào một buffer
      • ScatteringByteChannel: có thể đọc vào một trình tự của các buffer.
    • WriteableByteChannel: có thể ghi ra từ một buffer
      • GatheringByteChannel: có thể ghi từ một trình tự của các buffer.
    • ByteChannel: có thể đọc/ghi/ tới/từ một buffer
  • Channels: chứa các phương thức cho channel/stream interoperation

ReadableByteChannel interface định nghĩa một phương thức read mà đọc các byte từ channel vào một buffer, tương tự mới WriteableByteChannel interface định nghĩa một phương thức write mà ghi các byte từ một buffer vào channel. ByteChannel interface thông nhất 2 interface trên cho một trường hợp chung của channel mà có khả nằng vừa đọc và ghi các byte.

ScatteringByteChannel và GatheringByteChannel interface extend từ ReadableByteChannel và WritableByteChannel interface thêm 2 phương thức read, write, mà nhận một trình tự của các buffer thay vì duy nhất một buffer.

Channels class định nghĩa các phương thức static mà hỗ trợ interoperation của các stream class của gói java.io cùng với các channel class của gói đó. Một channel có thể được khởi tạo từ một InputStream hoặc OutputStream và ngược lại. Một Reader có thể được khởi tạo mà sử dụng nhận charset để decode các byte từ một readable byte channel, và ngược lại một Writer có thể được khởi tạo mà sử dụng một charset để encode các character thành các byte và ghi chúng vào một writable channel

Tuesday, June 18, 2013

NIO - Buffer

Buffer

  • Dùng để chứa dữ liệu của một primitive type nhất định
  • Buffer là một trình tự tuyến tính, hưu hạn
  • Có 3 thuộc tính chinh:
    1. Capacity: đại diện cho số lượng các phần tử mà nó chứa. C => 0 và không đổi
    2. Limit: là chỉ số của phần tử đầu tiên không thể đọc hoặc ghi. 0<= L <= C
    3. poisition: là chỉ số của phần tử tiếp theo được đọc hoặc ghi. 0 <= P <= L <= C









Truyền dữ liệu.
Mỗi một subclass của Buffer class định nghĩa 2 loại của hoạt động put và get:
  • Relative: đọc và ghi một hoặc nhiều phần tử bắt đầu ở position hiện tại sau đó tăng position lên tương ứng số lượng các phần tử được truyền. Nếu yêu cầu truyền dữ liệu vượt quá limit thì relative get  sẽ ném ra một BufferUnderflowExeption và relative put ném ra một BufferOverflowExeption, trong cả hai trường hợp này không có dư liệu được truyền.
  • Absolute: nhận một chỉ số phần tử chính xác không ảnh hưởng đến position. Ném ra một IndexOutOfBoundsExeption nếu chỉ số truyền vào vượt quá limit.
Mark  và resetting

Mark là chỉ số mà tới đó buffer position sẽ bị reset khi hàm reset được gọi. Mark không phải lúc nào cũng được định nghĩa, 0 <= M <= P <= L <= C. Nếu mark được định nghĩa nó sẽ hủy bỏ nếu position hoặc limit được điều chỉnh tới một giá trị nhỏ hơn mark. Nếu mark không được định nghĩa thì khi gọi hàm reset sẽ gây ra InvalidMarkException.

Khi mới khỏi tạo buffer position = 0, mark = undefined, limit có thể bằng 0 hoặc giá trị bất kì dựa trên kiêu của buffer và cách mà nó được khởi tạo. Content của buffer là undefined

Các Subclass:


  • ByteBuffer
    • MappedByteBuffer
  • CharBuffer
  • DoubleBuffer
  • FloatBuffer
  • IntBuffer
  • LongBuffer
  • ShortBuffer
Khởi tạo

Buffer được khởi tạo bởi 2 cách: sử dụng phương thức allocate hay allocateDirect, vốn nhận một tham số là một integer, ấn định capacity của Buffer. Điểm khác biện giữa 2 phương thức này là allocateDirect sẽ khởi tạo một buffer nằm bên ngoài heap của JVM, giúp bỏ bới thao tác copy dữ liệu giữa JVM buffer và OS buffer, kết quả là tăng tốc đáng kể tác vụ I/O. Tuy nhiên, việc này cũng có 1 tradeoff, đó là quy trình khởi tạo buffer sẽ tốn nhiều thời gian và công sức hơn. Tuy nhiên yếu điểm này cũng có thể giảm nếu sử dụng một vài practice đúng cách để tối ưu hóa.

Một số phương thức cơ bản

  • clear() làm cho buffer sẵn sàng cho một trình tự mới của channel-read hoặc relative put operation: nó thiết lập L = C, P = 0.
  • flip() làm cho buffer sẵn sàng cho một trình tự mới của channel-write hoặc relative get operation: nó thiết lập L = P, P = 0.
  • rewind() làm cho buffer sẵn sàng để đọc lại dữ liệu mà nõ đã có sẵn: không thay đổi limit, thiết lập P = 0.


Read-only buffers
Tất cả mọi buffer đều có thể đọc được, nhưng không phải tất cả có thể ghi. Các phương thức đột biến của từng lớp con được xác định như optional operations mà sẽ ném ra ReadOnlyBufferException khi được gọi trên một read-only buffer. Một read-only buffer không cho phép nội dung của nó bị sửa đổi, nhưng mark, postion, limit có thể thay đổi. Để xác định buffer read-only hay không sử dụng phương thức isReadOnly

Tông quan java nio

NIO APIs tập trung trừu tượng hóa:

  • Buffers, dùng để chứa dữ liệu.
  • Charsets và 2 thành phần liên quan dicoders và encoders, dùng để chuyển đổi dữa byte và unicode character.
  • Channels của những kiểu khác nhau, đại diên cho các kết nối của các thực thể có khả năng thực thi các hoạt động I/O.
  • Selectors và selection keys, cùng với selectable channels định nghĩa một cơ sở multiplexed, non-blocking I/O
Cấu trúc gói java.nio:

  • Các buffer class
  • Gói java.nio.charset.
  • java.nio.channels
Mỗi một subpackage đều có một service-provider supackage riêng, các nội dung của chúng có thể được sử dụng để mở rộng implementations mặc định hoặc khởi tạo.





Wednesday, March 20, 2013

API - Fragments

Fragments

- Một Fragment đại diện cho một hành động hoặc một phần của user interface trong một activity.
- Có thể kết hợp nhiều fragment trong cùng một actitvity để xây dựng một multi-pane UI và tái sử dụng một fragment trong nhiều actitvity
- Có thể coi fragment là một thành phần mô-đun của một actitvity, nó có lifecycle của riêng mình, tiếp nhận các event, và có thể thêm hoặc loại bỏ trong khi activity đang chạy.
- Fragment được nhúng vào một actitvity và fragment's lifecycle bị ảnh hưởng trực tiếp bời lifecycle của activity chứa nó. Ví dụ: khi activity paused tất cả fragment chứa trong nó đều paused.
- Tuy nhiên khi một activity đang chạy (trạng thái resumed) bạn có thể thao tác độc lập với mỗi fragment.

- Khi bạn thêm một fragment như một phần của layout activity, nó phải được đặt trong một ViewGroup và nằm bên trong hệ thống phân cấp activity's view
- Có thể thêm một fragment vào activity layout bằng cách khai báo một element <fragment> trong file layout hoặc từ code bằng cách thêm nó vào một ViewGroup có sẵn.
- Fragment không nhất thiết phải là một phần của activity layout, bạn có thể sử dụng một fragment mà không cần tới UI của nó như một thành phần ẩn của activity.

Tiêu chí thiết kế

Android đã giới thiệu fragment trong Android 3.0 (API level 11). Chủ yếu để hỗ trợ việc thiết kế UI linh động trên các màn hình lớn, như tablet. Màn hình tablets lớn hơn các thiết bị cầm tay vì thế có nhiều khoảng trống đề kết hợp và thay đổi các thành phần UI. Fragment cho phép thiết kế mà không cần bạn phải quản lý các thay đổi phức tạp của hệ thống phân cấp view. Bằng cách chia layout ra các fragment, bạn có thể chỉnh sửa cách thức xuất hiện của activity tại thời điểm runtime và bảo toàn các thay đổi của nó trong một back stack được quản lý bởi activity.

Ví dụ. Một ứng dụng sử dụng một fragment để hiển thị list các bài viết bên trái, và một fragment khác để hiển thị nội dung của bài viết đó bên phải. Cả 2 fragment xuất hiện trong một activity, ngay cạnh nhau. Mỗi fragment có một lifecycle riêng và xử lý các event của chúng.



Bạn nên thiết kết mỗi fragment như một mô-đun và có thể tái sử dụng. Mỗi fragment đều có layout, lifecycle và các hành vi riêng vì thế bạn có thể sử dụng 1 fragment trên nhiều activity. Tránh thao tác trực tiếp 1 fragment từ 1 fragment khác. Điều này đặc biệt quan trọng bởi vì một mô-đun fragment cho phép bạn thay đổi sự kết hợp fragment cho các kích thước màn hình khác nhau. Khi thiết kế ứng dụng để hỗ trợ cả tablets và cầm tay, bạn có thể tái sử dụng fragment trong các thiết lập layout khác nhau để tối ưu trải nghiệm người dùng dựa trên khoản không gian sẵn có của màn hình. Ví dụ trên các thiết bị cầm tay, bạn cần phải ngăn cách các fragment để cung cấp một single-pane UI trong khi không thể sử dụng nhiều fragment trong một layout.