Làm thế nào để chọn được ngôn ngữ thích hợp nhất?


Một câu hỏi thường gặp của những người mới bắt đầu lập trình là “Nên học hay nên dùng ngôn ngữ lập trình nào?”. Đây không chỉ là mối băn khoăn của các bạn trẻ chập chững bước vào thế giới “0 và 1” mà còn của cả những người trong nghề muốn củng cố hay nắm bắt cơ hội nghề nghiệp. Không có một qui tắc đơn giản để phân hạng các ngôn ngữ (NN). Mỗi NN đều có những điểm mạnh và điểm yếu. Một NN có thể “sáng chói” trong một số lĩnh vực nhưng trong một số lĩnh vực khác bạn lại phải “đánh vật” với nó. Sự lựa chọn NNLT có thể xem như vấn đề “tín ngưỡng” cá nhân. Tuy vậy, có một số cơ sở giúp bạn đưa ra quyết định đúng đắn.

Phân loại Ngôn ngữ lập trình
Ngôn ngữ lập trình (NNLT) là phương tiện để giao tiếp và ra lệnh cho máy tính thực hiện những công việc cụ thể. Máy tính chỉ có thể hiểu các con số 0 và 1, nhưng con người lại không thành thạo kiểu suy nghĩ với các con số này để ra lệnh cho máy tính. Vì vậy người ta đã phát triển các dạng câu lệnh mà con người có thể đọc hiểu, tập các câu lệnh này được gọi là mã nguồn (source code). Mã nguồn phải tuân thủ một tập các từ vựng, cú pháp và qui tắc do những người thiết kế NN đặt ra. Ví dụ, đoạn mã nguồn mẫu ra lệnh cho máy tính hiển thị dòng chữ “Xin chào.” trên màn hình:


#!/usr/bin/perl
print “Xin chào.”

Mã nguồn được một phần mềm thiết kế đặc biệt có thể hiểu các câu lệnh và dịch thành dạng mã mà máy có thể hiểu và thực thi.

Cấp thấp và cấp cao

Một cách tổng quát, một NNLT có 2 thành phần chính: (1) tập các thành phần cơ bản của NN (lệnh, hàm, thủ tục...) có thể kết hợp thành chương trình, và (2) bộ biên dịch để chuyển mã nguồn thành mã máy.



Những NNLT thế hệ đầu tiên gần gũi với mã máy và thường gắn chặt với nền tảng phần cứng, các thế hệ NNLT mới hơn gần gũi với con người hơn và ít lệ thuộc nền tảng phần cứng hơn. Xét theo khía cạnh này, có thể phân các NNLT thành 3 nhóm.  

1. Các NNLT cấp thấp (LLL - Low Level Language), 'hướng đến máy tính“, tương tác trực tiếp với phần cứng. Các NN này có tập lệnh tương ứng với tập lệnh của CPU. Có 2 loại NNLT cấp thấp: NN mã máy dùng các con số và NN Assembly dùng các từ gợi nhớ. Các NNLT cấp thấp nhanh và hiệu quả trong việc tương tác với phần cứng.

2. NNLT cấp cao (HLL - High Level Language), 'hướng đến nhiệm vụ“, có từ vựng giống tiếng Anh giúp dễ dàng trong việc viết chương trình. Các NN này có cú pháp chặt chẽ, có khả năng chạy trên nhiều hệ thống phần cứng khác nhau. Đa phần các phần mềm được phát triển dùng các NN này. Các NNLT quen thuộc trong nhóm này như C, C++, Pascal, Java...

3. NNLT cấp rất cao (VHLL - Very High Level Language), 'hướng đến con người“, được thiết kế để phát triển các ứng dụng chuyên biệt mà không đòi hỏi nhiều kiến thức về lập trình. Các NN này khá mới và vẫn đang tiếp tục phát triển. VHLL tương tự HLL nhưng dễ học và dễ sử dụng hơn. VHLL có nhiều loại, có thể kể 2 loại thông dụng nhất:

- Các NN tương tác (authoring) như NN đánh dấu (HTML, DHTML, XML) và NN mô hình (VRML) dùng để tạo trang web và nội dung đa phương tiện.

- Các NN kịch bản (scripting) như JavaScript dùng để viết các chương trình nhỏ đi kèm các trang web để tạo các hiệu ứng động và tương tác.

Tổng quát và chuyên biệt

Xét ở cấp độ tổng quát, tất cả các NNLT đều tương tự nhau. Chúng đều yêu cầu bạn 'mô tả“vấn đề cần giải quyết và đều đòi hỏi các kỹ năng tương tự. Nếu nắm vững một NN, bạn sẽ có đất để sử dụng những kỹ năng của mình với một NN khác. Nhưng thực tế ứng dụng có những NN thực hiện những kỹ thuật hay giải quyết những dạng vấn đề chuyên biệt dễ hơn những NN khác, và có những NN có khả năng thực hiện nhiều dạng ứng dụng.

Không có lằn ranh rõ ràng giữa các NN chuyên biệt và NN tổng quát. Tuy nhiên có thể phân định một cách đơn giản như sau: Các NN tổng quát được thiết kế để viết các chương trình lớn, có cú pháp phức tạp, thời gian biên dịch dài và phải thực hiện biên dịch trước, và có bộ thư viện riêng. Nói chung các NN tổng quát có thể dùng cho bất kỳ công việc tính toán nào, tuy nhiên thực tế thường mỗi NN thích hợp hơn với một lĩnh vực nhất định nào đó: Fortran thích hợp cho tính toán khoa học; Java dùng cho ứng dụng phân tán không lệ thuộc nền tảng hệ thống; C dùng cho lập trình hệ thống và trình biên dịch; Pascal thích hợp cho việc giảng dạy về lập trình...

Các NN chuyên biệt được thiết kế cho các chương trình nhỏ, cú pháp đơn giản, thường được biên dịch lúc thực thi, và có nhiều tác vụ xây dựng sẵn. Nói chung, các NN chuyên biệt chỉ dùng trong các ứng dụng chuyên biệt: Matlab dùng trong toán học, SQL dùng trong cơ sở dữ liệu, PHP dùng để tạo trang web...

Một số lĩnh vực ứng dụng đặc thù có thể dùng các NN tổng quát nhưng phải bổ sung thêm các hàm thư viện và môi trường đặc biệt. Ví dụ, lập trình đồ hoạ có thể dùng bất kỳ NN tổng quát nào kết hợp với một tập các hàm đồ hoạ.

Mô hình tính toán

Mô hình tính toán của một NNLT tổng quát có ảnh hưởng đến khả năng sử dụng của nó trong một lĩnh vực đặc thù. Có các mô hình tính toán chính: lệnh hay thủ tục (imperative, procedural), khai báo hay phi thủ tục (declarative, non-procedural), hướng đối tượng (object-oriented) và kịch bản (scripting).

Với các NN lệnh, chương trình bao gồm chuỗi lệnh mô tả cách thức thay đổi dữ liệu (trạng thái). Fortran, Cobol, C và  Pascal thuộc nhóm này.

Trong khi các NN lệnh chú trọng đến cách thức giải quyết vấn đề, các NN khai báo quan tâm đến vấn đề cần giải quyết, định nghĩa đầu vào và đầu ra của chương trình. Có 2 loại NN khai báo: NNLT chức năng như  Lisp và Haskell, và NNLT luận lý như Prolog.

Ở các NNLT hướng đối tượng, toàn bộ thông tin để giải quyết vấn đề (dữ liệu và tác vụ) được nhóm chung lại thành các đối tượng. Các NN hướng đối tượng thuần tuý như Smalltalk và Java chỉ hỗ trợ mô hình này, còn có NN lai như C++ hỗ trợ cả các mô hình khác.

Chọn NNLT

Hiện có rất nhiều NNLT (con số có thể lên đến hàng trăm). Mỗi NNLT đều có những điểm mạnh và điểm yếu. Có một số yếu tố kỹ thuật và cả phi kỹ thuật tác động đến việc chọn NNLT.

Yếu tố kỹ thuật

- Yêu cầu của ứng dụng: có những NN phù hợp với những ứng dụng đặc thù.

- Nền tảng hệ thống: Ứng dụng sẽ chạy trên nền Intel, Sun, HP hay máy chủ IBM? và hệ điều hành Windows, Sun Solaris, Linux hay IBM OS? Không phải tất cả các NNLT đều có thể chạy trên mọi nền tảng hệ thống.

- Phát triển và bảo trì: NN có hỗ trợ phát triển ứng dụng nhanh và dễ bảo trì?

- Công cụ hỗ trợ và tài liệu: Công cụ hỗ trợ thường là một trong những yếu tố then chốt trong việc chọn NN. Các NN có công cụ hỗ trợ và tài liệu tốt thường dễ phổ biến, ví dụ như Visual Basic.

Yếu tố phi kỹ thuật

- Sự phổ biến của NN: Sự phổ biến, theo nghĩa thị phần và số lập trình viên sử dụng NN, có ảnh hưởng đến việc chọn lựa NN. Với một NN phổ biến như C bạn sẽ dễ dàng tìm thấy nhiều nguồn tài liệu và sự trợ giúp hơn là một NN ít được dùng hơn như Ada.

- Kinh tế: NN có được hỗ trợ tốt bởi các tổ chức thương mại hay cộng đồng phát triển phần mềm miễn phí? (Nghĩa là trình biên dịch và môi trường phát triển của NN sẽ được tiếp tục phát triển trong tương lai).

Chọn đúng công cụ cho công việc

Thực sự, khó có thể nói NNLT nào tốt hơn. Với bất kỳ NN nào cũng đều có những chương trình được viết rất tốt hay dở tệ. Chất lượng của chương trình chịu ảnh hưởng bởi chất lượng của lập trình viên nhiều hơn là chất lượng của NN. NNLT khó nhất chính là NN đầu tiên mà bạn học. Có một số NN có thể giúp cho việc viết chương trình dễ hơn đối với một số dạng ứng dụng, và ngược lại. Ví dụ C rất mạnh về lập trình hệ thống nhưng nếu dùng để viết ứng dụng quản lý dữ liệu thì bạn sẽ phải vất vả xây dựng những thứ đã có sẵn trong dBase hay Foxpro.

Việc xác định các yêu cầu và mục đích sẽ giúp bạn chọn được NN thích hợp. Hãy chọn NN phù hợp với công việc, hay tốt hơn, chọn cả hai. Nếu bạn định viết ứng dụng có yêu cầu xử lý giao diện, nên chọn NN có hỗ trợ đồ họa, như Visual Basic chẳng hạn. Bạn có thể đặt câu hỏi 'NN nào thực hiện việc này dễ hơn?“ thay vì 'Làm thế nào để thực hiện việc này với C++?“.

Có thể ứng dụng của bạn có nhiều phần với nhiều yêu cầu khác nhau. Chẳng hạn như chương trình game, có những phần (gồm trí tuệ nhân tạo, luật chơi, giao diện người dùng...) chỉ yêu cầu việc xây dựng và thay đổi dễ dàng, nhưng không yêu cầu tốc độ; nhưng có những phần (như đồ họa) lại đòi hỏi tốc độ.

Một cái áo không bắt buộc dùng chỉ một màu. Trong lập trình cũng vậy, không nhất thiết phải dùng một NN cho toàn bộ chương trình. Có các cách thức cho phép bạn 'nhúng“ gần như bất kỳ NN nào vào một NN khác. Cách này giúp cho bạn khai thác ưu điểm của từng NN. Tuy nhiên nên cẩn thận, có quá nhiều 'màu sắc“ sẽ làm bạn rối trí!

Và một điều nên lưu ý: Không hẳn các NN mới hơn luôn là lựa chọn tốt hơn. C++ mới hơn C, thế nhưng C vẫn tồn tại vì vẫn có ưu thế về tốc độ và kích thước nhỏâ gọn.

Trở lại câu hỏi ban đầu, 'Nên học hay dùng ngôn ngữ lập trình nào?“, có thể bạn tìm thấy lời giải với vấn đề được đặt ngược lại: 'Để làm gì?“.

SỰ LỰA CHỌN CỦA CÁC NHÀ PHÁT TRIỂN

Theo số báo cáo Worldwide IT Benchmark 2003 của META Group, C++ và Java tiếp tục là các NNLT được lựa chọn hàng đầu để phát triển ứng dụng, chiếm tỉ lệ lần lượt là 18% và 16,7%. HTML, JavaScript, ASP và XML cũng là nhóm NNLT quan trọng chiếm vị trí thứ 3 với tỉ lệ 13,6%, năm trước nhóm NNLT này chiếm tỉ lệ 9,7%. Việc dễ lập trình cùng với xu hướng phát triển của web có lẽ là lý do của sự gia tăng này. Tuy rất nổi tiếng với công cụ phát triển mạnh và được nhiều người dùng nhưng vị trí của Visual Basic trong ngành công nghiệp phần mềm khá khiêm tốn, chiếm vị trí thứ 4 với tỉ lệ 9,8%.

Báo cáo cũng cho thấy Windows vẫn duy trì vị trí dẫn đầu trong lựa chọn nền tảng phát triển, chiếm tỉ lệ áp đảo 61,9% (năm 2002, 53,1%). Nền tảng IBM chiếm vị trí thứ 2 với tỉ lệ 18,3%. Vị trí thứ 3 thuộc về Sun Solaris, 9,4%.

Nhìn chung, số liệu của META Group có sự tương đồng (ngoại trừ trường hợp của VB) với số liệu của một trong những công ty phần mềm hàng đầu ở Việt nam, công ty ParagonSolutions (PSV).

NGÔN NGỮ LẬP TRÌNH

Đây là danh sách các NNLT, từ những NN đã có cách đây hàng chục năm đến những NN mới xuất hiện gần đây, chủ yếu là các NN tổng quát. Các NN được nhóm theo các tính năng tương đồng. Vì giá trị lịch sử, có một số NN “chết” hay ít được sử dụng hiện diện trong danh sách. Danh sách này có thể chưa đầy đủ.

NGÔN NGỮ MÁY dùng các số 0 và 1 để  “ra lệnh” cho bộ  xử  lý. Tập lệnh chỉ  tương thích trong cùng họ CPU và rất khó lập trình.

NGÔN NGỮ ASSEMBLY gần giống như NN máy nhưng có ưu điểm là tập lệnh dễ đọc . Nói chung mỗi lệnh trong Assembly (như MOV A,B) tương ứng với một lệnh mã máy (như 11001001). Chương trình Assembly được biên dịch trước khi thực thi. Nếu cần tốc độ và kích thước chương trình thật nhỏ, Assembly là giải pháp.

C đạt được sự thỏa hiệp giữa việc viết code hiệu quả của Assembly và sự tiện lợi và khả năng chạy trên nhiền nền tảng của NNLT cấp cao có cấu trúc. NN hơn 20 năm tuổi này hiện vẫn được tin dùng trong lĩnh vực lập trình hệ thống. Có các công cụ thương mại và miễn phí cho gần như mọi HĐH.

C++ là NN được dùng nhiều nhất hiện nay, đa số phần mềm thương mại được viết bằng C++. Tên của NN có lý do: C++ bao gồm tất cả ưu điểm của C và bổ sung thêm các tính năng hướng đối tượng. Có các công cụ thương mại và miễn phí cho gần như mọi HĐH.

C# [phát âm 'C sharp“] là lời đáp của Microsoft đối với Java. Do không đạt được thỏa thuận với Sun về vấn đề bản quyền, Microsoft đã tạo ra NN với các tính năng tương tự nhưng chỉ chạy trên nền Windows.

JAVA là phiên bản C++ được thiết kế lại hợp lý hơn, có khả năng chạy trên nhiều nền tảng; tuy nhiên tốc độ không nhanh bằng C++. Có các công cụ miễn phí và thương mại hỗ trợ cho hầu hết các HĐH hiện nay. Tuy Microsoft đã gỡ bỏ hỗ trợ Java khỏi cài đặt mặc định của các phiên bản Windows mới, nhưng việc bổ sung rất dễ dàng.

PASCAL được thiết kế chủ yếu dùng để dạy lập trình, tuy nhiên nó đã trở nên phổ biến bên ngoài lớp học. Pascal yêu cầu tính cấu trúc khá nghiêm ngặt. Có các công cụ thương mại và miễn phí cho DOS, Windows, Mac, OS/2 và các HĐH họ Unix. Trình soạn thảo website BBEdit được viết bằng Pascal.

DELPHI là phiên bản hướng đối tượng của Pascal được hãng Borland phát triển cho công cụ phát triển ứng dụng nhanh có cùng tên. Môi trường Delphi được thiết kế để cạnh tranh với Visual Basic của Microsoft, hỗ trợ xây dựng giao diện nhanh bằng cách kéo thả các đối tượng và gắn các hàm chức năng. Khả năng thao tác CSDL là một ưu điểm khác của NN. Borland, có các công cụ thương mại cho Windows và Linux.

BASIC ['Beginner’s All-purpose Symbolic Instruction Code“] là NNLT đầu tiên dùng cho máy vi tính thời kỳ đầu. Các phiên bản hiện đại của BASIC có tính cấu trúc hơn. Có các công cụ thương mại và miễn phí cho DOS, Windows, Mac và các HĐH họ Unix.

VISUAL BASIC [phiên bản của Basic cho môi trường đồ hoạ] là NN đa năng của Microsoft. Nó  bao gồm BASIC, NN macro của Microsoft Office (VBA – Visual Basic for Application), và công cụ phát triển ứng dụng nhanh. Tiếc là ứng dụng VB chỉ có thể chạy trên Windows và bạn bị lệ thuộc vào những chính sách thay đổi của Microsoft. (Chương trình viết bằng VB 6 hay các phiên bản trước sẽ không hoàn toàn tương thích với VB.NET)

ADA phần lớn dựa trên Pascal, đây là một dự án của Bộ Quốc Phòng Mỹ. ADA có nhiều điểm mạnh, như cơ chế kiểm soát lỗi, dễ bảo trì và sửa đổi chương trình. Phiên bản hiện thời có cả các tính năng hướng đối tượng.

ICON là NN thủ tục cấp cao. Xử lý văn bản là một trong những điểm mạnh của nó. Có các phiên bản cho Windows, HĐH họ Unix và các môi trường Java; các phiên bản cũ hơn hỗ trợ các HĐH khác.

SMALLTALK môi trường phát triển hướng đối tượng và đồ hoạ của Smalltalk chính là nguồn cảm hứng cho Steve Jobs và Bill Gates 'phát minh“ giao diện Mac OS và Windows.

RUBY hợp một số tính năng tốt nhất của nhiều NN khác. Đây là NN hướng đối tượng thuần túy như Smalltalk, nhưng có cú pháp trong sáng hơn. Nó có khả năng xử lý văn bản mạnh tương tự như Perl nhưng có tính cấu trúc hơn và ổn định hơn.

PERL thường được xem đồng nghĩa với “CGI Scripting”. Thực tế, Perl “lớn tuổi” hơn web. Nó  'dính“ vào công việc lập trình web do khả năng xử lý văn bản mạnh, rất linh động, khả năng chạy trên nhiều nền tảng và miễn phí.

TCL (phát âm 'tickle“) có thể tương tác tốt với các công cụ dùng văn bản như trình soạn thảo, trình biên dịch... dùng trên các HĐH họ Unix, và với phần mở rộng TK nó có thể truy cập tới các giao diện đồ hoạ như Windows, Mac OS và X-Windows, đóng vai trò kết dính các thành phần lại với nhau để hoàn thành các công việc phức tạp. Phương pháp mô-đun này là nền tảng của Unix

PYTHON là NN nguồn mở, hướng đối tượng, tương tác và miễn phí. Ban đầu được phát triển cho Unix, sau đó 'bành trướng“ sang mọi HĐH từ DOS đến Mac OS, OS/2, Windows và các HĐH họ Unix. Trong danh sách người dùng của nó có NASA và RedHat Linux.

PIKE cũng là NN nguồn mở, miễn phí được phát triển cho nhu cầu cá nhân, và hiện được công ty Roxen Internet Software của Thuỵ Điển phát triển dùng cho máy chủ web trên nền Roxen. Đây là NN hướng đối tượng đầy đủ, có cú pháp tương tự C, và có thể mở rộng để tận dụng các mô-đun và thư viện C đã biên dịch để tăng tốc độ. Nó có thể dùng cho các HĐH họ Unix và Windows.

PHP (Hypertext Pre-Processor) là NN mới nổi lên được cộng đồng nguồn mở ưa chuộng và là  mô-đun phổ biến nhất trên các hệ thống Apache (web server). Giống như CFML, mã lệnh nằm ngay trong trang web. Nó có thể dễ dàng truy cập tới các tài nguyên hệ thống và nhiều CSDL. Nó miễn phí và tính khả chuyển đối với các HĐH họ Unix và Windows.

MACROMEDIA COLDFUSION có mã lệnh CFML (Cold Fusion Markup Language) được nhúng trong trang web rất giống với thẻ lệnh HTML chuẩn. Rất mạnh, có các công cụ để truy cập nhiều CSDL và rất dễ học. Hạn chế chính của nó là giá cả, tuy nhiên có phiên bản rút gọn miễn phí. Chạy trên Windows và các HĐH họ Unix.

ACTIVE SERVER PAGES (ASP) được hỗ trợ miễn phí với máy chủ web của Microsoft (IIS). Thực sự nó không là NNLT, mà được gọi, theo Microsoft, là 'môi trường lập kịch bản phía máy chủ“.Nó dùng VBScript hay JScript để lập trình. Chỉ chạy trên Windows NT/2K. Microsoft đã thay NN này bằng ASP.NET, tuy có tên tương tự nhưng không phải là bản nâng cấp.

JAVASERVER PAGES (JSP) là NN đầy hứa hẹn. Nó dùng Java, có phần mềm máy chủ nguồn mở và miễn phí (Tomcat). Có thể chạy trên hầu hết các máy chủ web, gồm Apache, iPlanet và cả Microsoft IIS.

LISP ['LISt Processing“] là NNLT 'có thể lập trình“, được xây dựng dựa trên khái niệm đệ quy và có khả năng thích ứng cao với các đặc tả không tường minh. Nó có khả năng giải quyết những vấn đề mà các NN khác không thể, đó là lý do NN hơn 40 năm tuổi này vẫn tồn tại. Yahoo Store dùng Lisp.

PROLOG [“PROgramming in Logic”] được thiết kế cho các bài toán luận lý, ví dụ như “A bao hàm B, A đúng, suy ra B đúng” – một công việc khá khó khăn đối với một NN thủ tục.

COBOL [“Common Business-Oriented Language”] có tuổi đời bằng với điện toán thương mại, bị buộc  tội không đúng về vụ Y2K, và dù thường được dự đoán đến hồi cáo chung nhưng nó vẫn tồn tại nhờ tính hữu dụng trong các ứng dụng xử lý dữ liệu và lập báo cáo kinh doanh truyền thống. Hiện có phiên bản với các tính năng hướng đối tượng và môi trường phát triển tích hợp cho Linux và Windows.

FORTRAN [“FORmula TRANslation”] là NN xưa nhất vẫn còn dùng. Nó xuất sắc trong công việc đầu tiên mà máy tính được tin cậy: xử lý các con số. Theo đúng nghĩa đen, đây là NN đưa con người lên mặt trăng (dùng trong các dự án không gian), một số tính năng của NN đã được các NN khác hiện đại hơn “mượn”.

dBase [“DataBASE”] là NN lệnh cho chương trình quản lý CSDL mang tính đột phá của Ashton-Tate. Khi chương trình phát triển, NN cũng phát triển và nó trở thành công cụ phát triển. Tới thời kỳ xuất hiện nhiều công cụ và trình biên dịch cạnh tranh, nó chuyển thành chuẩn.

Foxpro là một nhánh phát triển của dBase dưới sự “bảo hộ” của Microsoft. Thực ra nó là công cụ phát triển hơn là NN. Tuy có lời đồn đại về sự cáo chung, nhưng NN vẫn phát triển. Hiện Foxpro có tính đối tượng đầy đủ và có công cụ phát triển mạnh (Visual Foxpro).

Erlang [“Ericsson LNAGuage”] thoạt đầu được hãng điện tử Ericsson phát triển để dùng riêng nhưng sau đó đưa ra bên ngoài như là phần mềm nguồn mở. Là NN cấp thấp xét theo việc nó cho phép lập trình điều khiển những thứ mà thường do HĐH kiểm soát, như quản lý bộ nhớ, xử lý đồng thời, nạp những thay đổi vào chương trình khi đang chạy... rất hữu ích trong việc lập trình các thiết bị di động. Erlang được dùng trong nhiều hệ thống viễn thông lớn của Ericsson.

HASKELL là NN chức năng, nó được dùng để mô tả vấn đề cần tính toán chứ không phải cách thức tính toán.

Microsoft Visual Studio làm cho mọi thứ trở nên dễ dàng miễn là bạn phát triển ứng dụng trên HĐH của Microsoft và sử dụng các NN cũng của Microsoft!

Borland cung cấp các công cụ phát triển tích hợp đầu tiên với tên “Turbo” và nhiều năm nay “lăng xê” một loạt các công cụ có thể chạy trên nhiều nền tảng. C++ Builder và Delphi là các công cụ mạnh để phát triển nhanh các ứng dụng Windows với C++ và Object Pasccal. Kylix đem các công cụ này sang Linux. JBuilder cung cấp các công cụ tương tự để làm việc với Java (có các phiên bản cho Windows, Mac OS, Linux và Solaris).  

Metrowerks CodeWarrior hỗ trợ nhiều nền tảng hơn bất kỳ công cụ phát triển nào (có thể kể một số như Windows, Mac OS, Linux, Solaris, Netware, PalmOS, PlayStation, Nintendo...). Công cụ có thể làm việc với nhiều NN: C, C++, Java và Assembly.

Macromedia Studio MX cung cấp mọi thứ cần thiết để tạo các ứng dụng internet và đa phương tiện, được xem như là giải pháp thay thế cho các công cụ lập trình truyền thống. Bộ công cụ kết hợp Dreamweaver và Flash, với các công cụ đồ hoạ Fireworks và Freehand, và máy chủ ColdFusion. Dreamweaver có thể dùng một mình, cho phép phát triển website có CSDL, lập trình với JSP, PHP, Cold Fusion và ASP. Flash cũng là môi trường lập trình mạnh, dùng để tạo ứng dụng đồ hoạ tương tác. Gần như các công cụ chính đều chạy trên Windows và Mac OS.

IBM VisualAge bành trướng gần như mọi hệ thống, từ máy tính lớn đến máy tính để bàn và thiết bị cầm tay. Các NN bao gồm, C++, Java, Smalltalk, Cobol, PL/I và PRG. VisualAge for Java là một trong các công cụ phát triển Java phổ biến nhất.

NetBeans là môi trường phát triển mô-đun, nguồn mở cho Java, được viết bằng Java. Điều này có nghĩa nó có thể dùng trên bất kỳ hệ thống nào có hỗ trợ Java (hầu hết các HĐH). Nó là cơ sở đề Sun xây dựng Sun One Studio, BEA dùng nó cho một phần của WebLogic.

Sun có các công cụ phát triển hiệu quả trong lĩnh vực của mình. Sun ONE Studio cho Java với cả bản thương mại và miễn phí. Sun ONE Studio Compiler Collection cho các nhà phát triển Unix, dùng C/C++. Với tính toán tốc độ cao, hãng có Forte for Fortran và High-Performance Computing.

Oracle JDeveloper thuộc bộ công cụ Internet Developer Suite. Nó chủ yếu dùng để phát triển các thành phần như servlet cho các ứng dụng web, và kết hợp tốt với CSDL Oracle.

WebGain VisualCafé chuyên hỗ trợ phát triển các ứng dụng phía server dùng Java. Công cụ gồm 2 phần: expert (cho ứng dụng phía client), và enteprise (cho ứng dụng server). Cả hai đều dùng Macromedia Dreamweaver Ultradev để xây dựng khung ứng dụng.

GNU Compiler Collection (GCC) là bộ công cụ miễn phí dùng để biên dịch chương trình chạy trên HĐH bất kỳ thuộc họ Unix. Hỗ trợ các NN: C, C++, Objective C, C, Fortran, Java và Ada. Một số công cụ đã được đưa sang DOS, Windows và PalmOS. Đây là các công cụ được lựa chọn của hầu hết các dự án nguồn mở và bản thân chúng cũng là nguồn mở. GCC không có môi trường phát triển ứng dụng tích hợp.

KDevelop là công cụ phát triển nguồn mở dùng để xây dựng các ứng dụng Linux dùng C++. Mặc dù có tên như vậy nhưng nó hỗ trợ giao diện GNOME cũng như KDE, ngoài các ứng dụng dùng Qt hay không có thành phần đồ họa.

Black Adder là công cụ phát triển mạnh cho các NN Python và Ruby. Có thể chạy trên Linux và Windows. Nó sinh mã để dùng các thành phần đồ họa Qt.

Intel/KAI cung cấp các công cụ phát triển nhắm đến các hệ thống đa xử lý và các HĐH họ Unix, dùng C/C++ và Fortran. Công cụ KAP cho phép chuyển các ứng dụng xử lý đơn sang kiến trúc đa xử lý.


Nguồn: PCworld.com.vn

[Tự học lập trình Android] Bài 7: Các kiểu lập trình sự kiện trong Android

Các kiểu lập trình sự kiện trong Android

Một số kiểu lập trình sự kiện phổ biến trong Android:
Onclick in XML
Inline anonymous listener
Activity is listener
Listener in variable
Explicit listener class
View Subclassing


Tìm hiểu các sự kiện qua các ví dụ mẫu

1. Onclick in XML

Ví dụ 1: Xây dựng ứng dụng tính tổng 2 số a và b, với giao diện như sau:
Hình 1

Khi nhấn vào nút “Tổng 2 số”, sẽ in ra tổng 2 số vừa nhập.

- Bạn xem Layout Outline để dễ thiết kế (chú ý là bạn có thể bỏ LinearLayout1 đi):

Hình 2

Chú ý: là ta sử dụng Onclick in XML:
Hình 3
- Trong đoạn lệnh ở trên thì ta sử dụng android:conClick="btn_tong2so", tức là ta đã gán một sự kiện click cho Button này, sự kiện này tên là btn_tong2so. Ta cần khai báo một hàm btn_tong2so ở trong Activity class như hình bên dưới:
Hình 4

- Khi chạy ứng dụng bạn sẽ được kết quả như bên dưới:

Hình 5

2. Inline anonymous listener

Ví dụ 2: Xây dựng ứng dụng chuyển đổi năm dương lịch qua năm âm lịch như hình bên dưới:
Hình 6

- Khi người sử dụng nhập vào EditText giá trị là 1 năm Dương Lịch bất kỳ nào đó rồi nhấn nút “Chuyển đổi”, chương trình sẽ chuyển năm dương lịch thành năm âm lịch. Trong ví dụ trên nếu người sử dụng nhập 2013 thì sẽ ra năm âm lịch là “Quý Tỵ”.

Chú ý: là ta tạo một anonymous listener, trước tiên bạn hãy xem Outline XML để cho dễ bề thiết kế:

Hình 7

- Để chuyển từ năm dương lịch sang năm âm lịch bạn cần biết một số thông tin sau:
Hình 8

- Bây giờ ta tiến hành gán sự kiện cho nút “Chuyển đổi” (ở đây id Tôi để là button1), mở Activity class lên vào sửa lệnh như bên dưới:
Hình 9

- Bạn tự đưa lệnh vào Bước 1, Bước 2, bước 3 ở trên. Cách lấy dữ liệu nhập vào từ EditText đã hướng dẫn ở phần Onclick in XML, làm theo cái này để lấy được giá trị là năm dương lịch ra, sau đó lấy năm này xử lý theo bảng Can và Chi như hướng dẫn thì Ta sẽ ra được năm Âm lịch tương ứng.

3. Activity is listener
Ví dụ: Hãy xây dựng ứng dụng tính Chỉ số khối cơ thể - BMI (Body Mass Index ), BMI được dùng để đánh giá mức độ gầy hay béo của một người. Chỉ số này có thể giúp xác định một người bị bệnh béo phì hay bị bệnh suy dinh dưỡng.

- Trong cách viết sự kiện này thì Activity sẽ implements interface có kiểu sự kiện (rất nhiều loại interface). Trong ví dụ này ta xét trường hợp cho Button còn các trường hợp khác các bạn tự tìm hiểu và suy luận ra.

+ Cách tính như sau:

Gọi W là khối lượng của một người (tính bằng kg) và H là chiều cao của người đó (tính bằng m), chỉ số khối cơ thể được tính theo công thức:
Hình 10

Phân loại để đánh giá như sau:

 BMI < 18: người gầy
 BMI = 18 – 24,9: người bình thường
 BMI = 25 – 29,9: người béo phì độ I
 BMI = 30 – 34,9: người béo phì độ II
 BMI > 35: người béo phì độ III

Thiết kế giao diện như hình bên dưới và cung cấp Outline, các bạn hãy thiết kế lại để nâng cao kinh nghiệm:
Hình 11

- Ví dụ thông số: chiều cao 1.68 mét, cân nặng 58 kg. Click “Tính BMI” thì chương trình sẽ tính ra được BMI của Tôi là 20.5 và chẩn đoán là “Bình thường”.

- Xem Outline của giao diện này dưới đây (các bạn có thể tìm hiểu thêm):
Hình 12

- Nội dung Coding trong Activity:

import java.text.DecimalFormat;
import android.os.Bundle;
import android.app.Activity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText; 


public class MainActivity extends Activity implements OnClickListener{
  Button btnChandoan;
  EditText editTen,editChieucao, editCannang,editBMI,editChandoan;

@Override

protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  btnChandoan=(Button) findViewById(R.id.btntinhBMI);
  btnChandoan.setOnClickListener(this);
  editTen=(EditText) findViewById(R.id.editten);
  editChieucao=(EditText) findViewById(R.id.editchieucao);
  editCannang=(EditText) findViewById(R.id.editcannang);
  editBMI=(EditText) findViewById(R.id.editBMI);
 editChandoan=(EditText) findViewById(R.id.editChanDoan);
}

@Override

public void onClick(View arg0) {
  double H=Double.parseDouble(editChieucao.getText()+"");
  double W=Double.parseDouble(editCannang.getText()+"");
  double BMI=W/Math.pow(H, 2);
  String chandoan="";
  if(BMI<18)
  {
    chandoan="Bạn gầy";
   }
  else if(BMI<=24.9)
  {
   chandoan="Bạn bình thường";
  }
  else if(BMI<=29.9)
  {
    chandoan=”Bạn béo phì độ 1″;
   }
   else if(BMI<=34.9)
  {
     chandoan="Bạn béo phì độ 2″;
   }
   else
  {
    chandoan="Bạn béo phì độ 3″;
   }
  DecimalFormat dcf=new DecimalFormat(“#.0″);
  editBMI.setText(dcf.format(BMI));
  editChandoan.setText(chandoan);
 }
}


- Ta thấy class Activity đã implements interface OnClickListener
- Bản thân interface OnClickListener có mộ Abstract Method là onClick (View arg0) nên ta phải Override nó.
- Để Button có thể hiểu được sự kiện thì ta phải gọi dòng lệnh: btnChandoan.setOnClickListener(this); bản thân Activity là một sự kiện nên ta dùng this để truyền vào hàm.
- Sử dụng: DecimalFormat dcf=new DecimalFormat(“#.0“); // Mục đích là định dạng 1 số lẻ thập phân, bạn muốn 2 số lẻ thập phần thì ghi “#.00″ hay muốn 3 thì “#.000″ …

4) Listener in variable
Ví dụ: Xây dựng ứng dụng (hình dưới):
Hình 13

- Tương tự như Activity Is listener, nhưng khác ở chỗ thay vì implement interface cho Activity thì nó lại được lưu trữ vào một biến có kiểu Listener trong activity. Làm cách này thì ta có thể chia sẻ chung một biến sự kiện cho các control khác nhau.
- Ở trên khai báo 1 biến có kiểu listener là interface OnClickListener.
- Và biến này sẽ được chia sẻ cho 2 Button Login và Cancel.
- Ví dụ Chuyển đổi độ F qua C và ngược lại. Bạn xem giao diện bên dưới:
Hình 14

- Giao diện bên trên sẽ có 3 button. Ta sẽ tạo một biến sự kiện và chia sẻ cho 3 Button ở trên.
- Bạn xem Outline để thiết kế:

Hình 15

- Đây là công thức chuyển đổi:

Hình 16
- Coding Activity:

import android.os.Bundle;
import android.app.Activity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends Activity {
  private Button btnFar,btnCel,btnClear;
  private EditText txtFar,txtCel;

private OnClickListener myVarListener=new OnClickListener() {

@Override

public void onClick(View arg0) {
  //Lấy F và C từ control ở đây
   if(arg0==btnFar)
   {
     //Bạn xử lý chuyển đổi F–>C theo công thức
   }
   else if(arg0==btnCel)
   {
    //Bạn xử lý chuyển đổi C–>F theo công thức
   }
   else if(arg0==btnClear)
  {
   txtFar.setText(“”);
   txtCel.setText(“”);
   txtFar.requestFocus();
  }
}
};

@Override

protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  btnFar = (Button)findViewById(R.id.btnFar);
  btnCel = (Button)findViewById(R.id.btnCel);
  btnClear = (Button)findViewById(R.id.btnClear);
  txtFar = (EditText)findViewById(R.id.txtFar);
  txtCel = (EditText)findViewById(R.id.txtCel);
  btnFar.setOnClickListener(myVarListener);
  btnCel.setOnClickListener(myVarListener);
  btnClear.setOnClickListener(myVarListener);
 }
}


Bạn tự viết lệnh cho 2 nút chuyển đổi: cách lấy dữ liệu đã hướng dẫn ở những kiểu lập trình sự kiện trước, bắt buộc bạn phải lấy được. Sau khi lấy được thì chỉ cần ráp vào công thức là xong.

5) Explicit listener class
- Trường hợp này ta tách riêng một class đóng vai trò là class sự kiện riêng.
- Khi nào lượng coding trong ứng dụng khổng lồ và phức tạp thì ta nên tách class sự kiện riêng để dễ quản lý.
Tôi ví dụ giải phương trình bậc 2, bạn xem giao diện bên dưới:
 
Hình 17

- Khi chọn “Tiếp tục”, chương trình sẽ xóa trắng toàn bộ dữ liệu trên màn hình đồng thời focus tới ô Nhập a.
- Khi chọn “Giải PT”, chương trình sẽ tiến hành lấy thông số a,b,c và tiến hành giải phương trình bậc 2 và cho ra kết quả như hình trên.
- Khi chọn “Thoát”, chương trình sẽ được đóng lại.
- Bạn xem Outline dưới đây:
Hình 18
- Tiến hành coding, bạn mở Activity class và coding như bên dưới:

import java.text.DecimalFormat;
import android.os.Bundle;
import android.app.Activity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends Activity {
  Button btnTieptuc,btnGiai,btnThoat;
  EditText edita,editb,editc;
  TextView txtkq;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    btnTieptuc=(Button) findViewById(R.id.btntieptuc);
    btnGiai=(Button) findViewById(R.id.btngiaipt);
    btnThoat=(Button) findViewById(R.id.btnthoat);
    btnTieptuc.setOnClickListener(new MyEvent());
    btnGiai.setOnClickListener(new MyEvent());
    btnThoat.setOnClickListener(new MyEvent());
   edita=(EditText) findViewById(R.id.edita);
   editb=(EditText) findViewById(R.id.editb);
   editc=(EditText) findViewById(R.id.editc); 

   txtkq=(TextView) findViewById(R.id.txtkq);
  }
 public void giaiPtb2()
 {
   String sa=edita.getText()+”";
   String sb=editb.getText()+”";
   String sc=editc.getText()+”";
   int a=Integer.parseInt(sa);
   int b=Integer.parseInt(sb);
   int c=Integer.parseInt(sc);
   String kq=”";
   DecimalFormat dcf=new DecimalFormat(“#.00″);
  if(a==0)
  {
     if(b==0)
     {
       if(c==0)
          kq=”PT vô số nghiệm”;
       else
         kq=”PT vô nghiệm”;
      }
  else
  {
    kq=”Pt có 1 No, x=”+dcf.format(-c/b);
   }
 }
 else
 {
  double delta=b*b-4*a*c;
   if(delta<0)
   {
      kq=”PT vô nghiệm”;
   }
   else if(delta==0)
  {
     kq=”Pt có No kép x1=x2=”+dcf.format(-b/(2*a));
   }
   else
  {
     kq=”Pt có 2 No: x1=”+dcf.format((-b-Math.sqrt(delta))/(2*a))+
     “; x2=”+dcf.format((-b-Math.sqrt(delta))/(2*a));
   }
  }
  txtkq.setText(kq);
}
private class MyEvent implements OnClickListener
{
 @Override
  public void onClick(View arg0) {
  if(arg0==btnTieptuc)
  {
   edita.setText(“”);
   editb.setText(“”);
   editc.setText(“”);
   edita.requestFocus();
  }
  else if(arg0.getId()==R.id.btngiaipt)
  {
    giaiPtb2();
  }
  else if(arg0.getId()==R.id.btnthoat)
  {
   finish();
  }
 }
}
}


- Bạn quan sát coding ở bên trên. Tạo một lớp sự kiện tên là MyEvent, control nào muốn được gán sự kiện chỉ cần gọi lệnh giống như gán cho Button Giải phương trình:

btnGiai.setOnClickListener(new MyEvent());

6. View Subclassing
- Kỹ thuật này không được phổ biến cho lắm. Bạn chỉ sài khi thêm Control động (lúc runtime) vào màn hình. Ta có thể dùng bất kỳ kỹ thuật nào (6 cách Tôi vừa nêu) để thêm sự kiện động cho một Button động.
-Ở cách cuối cùng này thì bạn phải override phương trình performClick của chính Button control:
Hình 19
- Như vậy các bạn đã được thực hành về các kiểu lập trình sự kiện trong Android, biết được cách lấy dữ liệu từ EditText, biết xử lý định dạng dữ liệu, củng cổ thêm được Layout.
- Trong các bài tập sắp tới các bạn sẽ được thực hành về Toast & Alert Dialog, và rất nhiều các control cơ bản cũng như nâng cao trong Android .
- Bạn phải hiểu rõ các kỹ thuật lập trình này để tùy vào từng trường hợp cụ thể mà bạn nên quyết định kỹ thuật nào cho phù hợp.

Tham khảo: duythanhcse

*******

Một số tài liệu và khoá học bổ ích dành cho bạn: 

# Giáo trình: Lập Trình Android [Click để xem]

# Khoá học online:  Lập trình Android toàn tập [Click để xem]

-----------------------------------------
Xem thêm bài và ví dụ khác:

 

[Tự học lập trình Android] Bài 14: Tìm hiểu về Tab Selector trong Android

Tìm hiểu về Tab Selector trong Android

- Tab Selector giống như Property Sheet trong Visual C, giống như Tab Control C#, hay trong Java:
Hình 1

- Đối với Android, mỗi Tab bạn nên thiết kế trên một Layout khác nhau, rồi trong Main Layout bạn chứa các tab đó vào (Tức là nếu như ứng dụng bạn có 3 Tab con thì sẽ tạo 3 Layout khác nhau rồi include chúng vào Main layout, chứ đừng thiết kế tất tần tật trong một Main Layout nó sẽ gây khó khăn trong việc sửa lỗi).
- Tôi trình bày sơ qua lý thuyết về Tab selector:
+ Tab selector gồm có 3 phần: Tab Host, Tab Widgets và FrameLayout.
Hình 2

+Tab Host: Là Container chính chứa các Tab buttons và Tab contents
+Tab Widget: Để định dạng cho các Tab buttons : Nhãn, Icon…
+FrameLayout: là Container để chứa các layout cho Tab contents, ta chỉ có thể dùng FrameLayout cho Tab contents, không thể dùng các loại Layout khác. Nếu bạn thắc mắc tại vì sao lại là FrameLayout mà không phải là các Layout khác? thì Tôi chỉ nói đơn giản thế này: Cho dù bạn có nhấn vào các Tab nào đi nữa thì layout tương ứng với mỗi Tab mà bạn vừa nhấn vào cũng chỉ xuất hiện cùng một chỗ trên màn hình điện thoại, điều này chỉ có FrameLayout mới giải quyết được.

*** Hình minh họa về giao diện trong bài ví dụ Tab Selector của Tôi như sau:
Hình 3
- Tab đầu tiên “1-CALCULATOR” là giao diện cho phép tính công trừ nhân chia, Tab thứ 2 “2-HISTORY” dùng để hiển thị danh sách các phép toàn đã thực hiện.
- Cấu trúc tổng quan của ứng dụng:
Hình 4

- Vì ứng dụng của Tôi có 2 Tab nên Tôi sẽ tạo 2 tabs: tab1_layout.xml và tab2_layout.xml, 2 tabs này sẽ được chứa vào main layout activity_main.xml, vậy tổng cộng Tôi có 3 Layout.
- Ta vào xem main layout (activity_main.xml):
- Xem Outline để dễ tưởng tượng:
Hình 5

-Còn đây là source XML:

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<TabHost
android:id="@android:id/tabhost"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TabWidget
android:id="@android:id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</TabWidget>
<FrameLayout
android:id="@android:id/tabcontent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/tab1"
android:layout_width="match_parent"
android:layout_height="match_parent">
<includelayout="@layout/tab1_layout"/>
</LinearLayout>
<LinearLayout
android:id="@+id/tab2"
android:layout_width="match_parent"
android:layout_height="match_parent">
<includelayout="@layout/tab2_layout"/>
</LinearLayout>
</FrameLayout>
</LinearLayout>
</TabHost>
</LinearLayout>

- Bạn nhìn vào dòng lệnh 30 và 36:

<include layout=”@layout/tab1_layout”/>
<include layout=”@layout/tab2_layout”/>

Đó chính là cách include một layout này vào trong một layout khác.

- Tiếp tục ta xem tab1_layout.xml, Tôi lấy lại bài tập trước về cộng trừ nhân chia:

<TableLayoutxmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/TableLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:stretchColumns="*">
<TableRow
android:id="@+id/tableRow1"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_span="4"
android:background="#5B8020"
android:gravity="center"
android:text="Cộng trừ nhân chia"
android:textColor="#FFFFFF"
android:textSize="20sp"/>
</TableRow>
<TableRow
android:id="@+id/tableRow2"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Số a:"/>
<EditText
android:id="@+id/editsoa"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_span="3"
android:ems="10"
android:inputType="number">
<requestFocus/>
</EditText>
</TableRow>
<TableRow
android:id="@+id/tableRow3"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Số b:"/>
<EditText
android:id="@+id/editsob"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_span="3"
android:ems="10"
android:inputType="number"/>
</TableRow>
<TableRow
android:id="@+id/tableRow4"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button
android:id="@+id/btncong"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="+"/>
<Button
android:id="@+id/btntru"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="-"/>
<Button
android:id="@+id/btnnhan"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="*"/>
<Button
android:id="@+id/btnchia"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="/"/>
</TableRow>
<TableRow
android:id="@+id/tableRow5"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/txtketqua"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_span="4"
android:background="#5B8020"
android:textColor="#FFFFFF"
android:textSize="25sp"/>
</TableRow>
</TableLayout>

- Và xem tiếp tab2_layout.xml, đơn giản là chỉ có 1 ListView chứa danh sách các phép toán đã thực hiện bên Tab1:

<?xmlversion="1.0"encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ListView
android:id="@+id/lvhistory"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</ListView>
</LinearLayout>

- Giờ bạn xem MainActivity để biết được cách cấu hình Tabhost:

importjava.util.ArrayList;
importandroid.os.Bundle;
importandroid.app.Activity;
importandroid.view.View;
importandroid.view.View.OnClickListener;
importandroid.widget.ArrayAdapter;
importandroid.widget.Button;
importandroid.widget.EditText;
importandroid.widget.ListView;
importandroid.widget.TabHost;
importandroid.widget.TextView;
importandroid.widget.Toast;

publicclassMainActivity extendsActivity {
//Enum để thực hiện phép toán
enumOperator
{
Cong,//phép cộng
Tru,//phép trừ
Nhan,//phép nhân
Chia//phép chia
}
Button btncong,btntru,btnnhan,btnchia;
EditText editsoa,editsob;
TextView txtkq;
ListView lvHistory;
ArrayList<String>array_operator=newArrayList<String>();
ArrayAdapter<String>adapter=null;
//Variable in listener
OnClickListener myclick=newOnClickListener() {
@Override
publicvoidonClick(View arg0) {
switch(arg0.getId())
{
caseR.id.btncong:
{
processOperator(Operator.Cong);
}
break;
caseR.id.btntru:
{
processOperator(Operator.Tru);
}
break;
caseR.id.btnnhan:
{
processOperator(Operator.Nhan);
}
break;
caseR.id.btnchia:
{
processOperator(Operator.Chia);
}
}
}
};

publicvoidprocessOperator(Operator op)
{
String sa=editsoa.getText()+"";
String sb=editsob.getText().toString();
inta=Integer.parseInt(sa);
intb=Integer.parseInt(sb);
String kq="";
switch(op)
{
caseCong:
kq=a+" + "+b +" = "+(a+b);
break;
caseTru:
kq=a+" - "+b +" = "+(a-b);
break;
caseNhan:
kq=a+" * "+b +" = "+(a*b);
break;
caseChia:
if(b!=0)
kq=a+" / "+b +" = "+(a*1.0/b);
else
kq="b phai khac 0";
break;
default:
kq="Invalid operator!";
}
txtkq.setText(kq);
array_operator.add(kq);
adapter.notifyDataSetChanged();
}
@Override
protectedvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
loadTabs();
doFormWidgets();
}
//Cấu hình tab
publicvoidloadTabs()
{
//Lấy Tabhost id ra trước (cái này của built - in android
finalTabHost tab=(TabHost) findViewById(android.R.id.tabhost);
//gọi lệnh setup
tab.setup();
TabHost.TabSpec spec;
//Tạo tab1
spec=tab.newTabSpec("t1");
spec.setContent(R.id.tab1);
spec.setIndicator("1-Calculator");
tab.addTab(spec);
//Tạo tab2
spec=tab.newTabSpec("t2");
spec.setContent(R.id.tab2);
spec.setIndicator("2-History");
tab.addTab(spec);
//Thiết lập tab mặc định được chọn ban đầu là tab 0
tab.setCurrentTab(0);
//Ở đây Tôi để sự kiện này để các bạn tùy xử lý
//Ví dụ tab1 chưa nhập thông tin xong mà lại qua tab 2 thì báo...
tab.setOnTabChangedListener(new
TabHost.OnTabChangeListener() {
publicvoidonTabChanged(String arg0) {
String s="Tab tag ="+arg0 +"; index ="+
tab.getCurrentTab();
Toast.makeText(getApplicationContext(),
s, Toast.LENGTH_LONG).show();}
});
}
//Khởi tạo các đối tượng và gán ADapter cho ListView
publicvoiddoFormWidgets()
{
btncong=(Button) findViewById(R.id.btncong);
btntru=(Button) findViewById(R.id.btntru);
btnnhan=(Button) findViewById(R.id.btnnhan);
btnchia=(Button) findViewById(R.id.btnchia);
editsoa=(EditText) findViewById(R.id.editsoa);
editsob=(EditText) findViewById(R.id.editsob);
txtkq=(TextView) findViewById(R.id.txtketqua);
lvHistory=(ListView) findViewById(R.id.lvhistory);
btncong.setOnClickListener(myclick);
btntru.setOnClickListener(myclick);
btnnhan.setOnClickListener(myclick);
btnchia.setOnClickListener(myclick);
adapter=newArrayAdapter<String>(this,android.R.layout.simple_list_item_1,array_operator);
lvHistory.setAdapter(adapter);
}
}


Tham khảo: duythanhcse

*******

Một số tài liệu và khoá học bổ ích dành cho bạn: 

# Giáo trình: Lập Trình Android [Click để xem]

# Khoá học online:  Lập trình Android toàn tập [Click để xem]


-----------------------------------------