Trang chủ > Phát triển di động > Nội dung chính

Quản lý thông báo số và dấu đỏ bằng mô hình cây


Hầu hết các ứng dụng mà chúng ta thường sử dụng hàng ngày đều có cách thông báo mới dựa trên số hoặc biểu tượng chấm đỏ. Ví dụ như trong ứng dụng WeChatkết quả bóng đá ngoại hạng anh, khi bạn bè gửi tin nhắn trò chuyện mới cho bạn, một con số sẽ xuất hiện trên cuộc trò chuyện tương ứng để chỉ ra số lượng tin nhắn chưa đọc. Hoặc nếu có người đăng bài mới trên trang (), một dấu chấm đỏ sẽ xuất hiện tại lối vào của phần này. Đặc biệt hơn, khi có ai đó thích bài viết của bạn hoặc để lại bình luận trên nội dung bạn đăng tải, lối vào sẽ hiển thị thêm một con số để thông báo chính xác số lượng hoạt động mới mà bạn nhận được từ bạn bè. Ứng dụng không chỉ đơn thuần là thông báo qua số lượng hay dấu chấm đỏ mà còn giúp người dùng dễ dàng theo dõi mọi tương tác mà họ nhận được, từ đó tạo nên sự kết nối nhanh chóng và tiện lợi giữa các cá nhân. Chính những chi tiết nhỏ nhặt như vậy đã góp phần làm cho trải nghiệm của người dùng trở nên thú vị và hữu ích hơn mỗi khi mở ứng dụng.

Tuy nhiênboi tu vi, khi thử nghiệm một số sản phẩm ứng dụng mới, chúng ta thường gặp phải nhiều vấn đề liên quan đến việc hiển thị số và chấm đỏ. Có những trường hợp, dù đã cố gắng nhấn mãi nhưng chấm đỏ vẫn không thể biến mất; hoặc, khi phát hiện có số hiển thị, nhưng khi nhấp vào bên trong thì lại chẳng thấy gì cả; thậm chí, đôi khi con số bên trong khác hoàn toàn so với con số được nhìn thấy từ bên ngoài. Những điều này thực sự gây khó chịu và làm giảm trải nghiệm người dùng.

Vậy những vấn đề này thực sự được tạo ra như thế nào?

Tôi cho rằngVSBET, nguyên nhân gốc rễ của vấn đề nằm ở chỗ chưa có một cách tiếp cận thống nhất để khái quát hóa và quản lý logic hiển thị của các con số và chấm đỏ. Điều này dẫn đến việc mối quan hệ giữa các con số và chấm đỏ trở nên phức tạp, mỗi thay đổi nhỏ đều có thể ảnh hưởng đến toàn bộ hệ thống. Do đó, trong quá trình duy trì ứng dụng (App), chỉ cần thực hiện một số điều chỉnh nhỏ (như thêm vài loại con số hoặc chấm đỏ), nguy cơ phát sinh lỗi sẽ rất cao. Thêm vào đó, khi không có cấu trúc rõ ràng, việc mở rộng hoặc bảo trì sẽ trở nên khó khăn hơn nhiều. Các lập trình viên phải dành thời gian tìm hiểu toàn bộ hệ thống thay vì tập trung vào cải tiến tính năng mới, làm giảm hiệu quả công việc và tăng nguy cơ sai sót trong quá trình sửa lỗi.

Bài viết này sẽ giới thiệu một mô hình cấu trúc cây để quản lý đồng bộ hóa cơ cấu cấp bậc giữa các số và chấm đỏ. Cuối bàiVSBET, chúng tôi cũng sẽ cung cấp một ứng dụng demo chạy được phiên bản Android làm ví dụ tham khảo cho người đọc.

Nếu bạn hiện đang có trong tay một điện thoại thông minh chạy hệ điều hành AndroidVSBET, bạn có thể quét mã QR bên dưới (hoặc nhấp vào đường link tải xuống dưới mã QR) để tải về và cài đặt phiên bản demo này. Chỉ cần dành ra vài phút để khám phá xem nó có phù hợp với nhu cầu của bạn hay không.

Demo APK Download

Hoặc nhấn vào Liên kết tải xuống

Cách quản lý số và thông báo đỏ đơn giản

Để thuận tiện cho việc thảo luậnboi tu vi, chúng ta hãy bắt đầu bằng cách sắp xếp một cách đơn giản các yêu cầu về việc hiển thị số và chấm đỏ trong trường hợp thông thường. Sau đó, chúng ta sẽ xem xét cách thức thực hiện trực quan nhất có thể dựa trên những yêu cầu này. Trước tiên, điều quan trọng là phải hiểu rõ hơn về mục đích của việc sử dụng số và chấm đỏ. Điều này không chỉ giúp chúng ta xác định cách bố trí mà còn giúp tăng cường hiệu quả giao tiếp qua hình ảnh. Ví dụ, nếu số cần được hiển thị ở giữa và chấm đỏ phải nằm ngay bên cạnh hoặc phía dưới để tạo sự chú ý, thì chúng ta cần thiết kế một cấu trúc logic để đảm bảo rằng cả hai yếu tố đều dễ dàng nhận biết và phân biệt. Tiếp theo, khi đã hiểu rõ các yêu cầu cơ bản, chúng ta có thể tìm ra phương án thực hiện nhanh chóng và hiệu quả nhất. Có thể sử dụng các công cụ đồ họa hiện đại hoặc lập trình với ngôn ngữ phù hợp để đạt được kết quả mong muốn. Điều này không chỉ tiết kiệm thời gian mà còn tối ưu hóa trải nghiệm người dùng. Tóm lại, việc sắp xếp nhu cầu một cách có hệ thống và chọn giải pháp trực quan sẽ giúp chúng ta đạt được mục tiêu nhanh chóng và hiệu quả.

  • Một số tin tức mới rất quan trọng và cần được thể hiện dưới dạng con số; trong khi đóboi tu vi, những tin tức khác không quá cấp thiết và chỉ cần được biểu thị bằng chấm đỏ. Chẳng hạn, khi tôi nhận được bình luận mới hoặc có người thích bài viết của mình, việc thể hiện thông tin này dưới dạng số sẽ hợp lý hơn. Ngược lại, với những thông báo từ hệ thống mà tôi không muốn làm phân tâm quá nhiều, một dấu chấm đỏ nhẹ nhàng sẽ là cách phù hợp để thu hút sự chú ý mà không gây khó chịu.
  • Số và chấm đỏ đóng vai trò như những tín hiệu phân cấp mà người dùng có thể dựa vào để khám phá sâu hơn vào các trang trong ứng dụng. Khi có thông báo mớiboi tu vi, người dùng có thể bắt đầu từ trang chủ (trang cấp độ đầu tiên) và lần theo các dấu hiệu số và chấm đỏ để đi sâu dần vào các trang cụ thể hơn, cuối cùng đến trang đích hiển thị thông báo mới. Ví dụ, trong hình ảnh chụp màn hình dưới đây của ứng dụng, khi người dùng nhận được một bình luận mới, trước tiên sẽ xuất hiện một số ở tab thứ hai (tab “Thông báo”), dẫn dắt người dùng chuyển sang tab này. Sau đó, trên trang này, bên cạnh mục “Bình luận nhận được”, sẽ tiếp tục xuất hiện số để khuyến khích người dùng nhấn vào và đi sâu hơn vào trang chi tiết về bình luận. Cách thiết kế này không chỉ giúp tạo sự chú ý mà còn mang lại trải nghiệm trực quan cho người dùng, giúp họ dễ dàng tìm kiếm và quản lý thông tin mới một cách nhanh chóng và hiệu quả. Đồng thời, nó cũng tăng cường khả năng tương tác giữa người dùng và ứng dụng, làm cho việc sử dụng trở nên thú vị hơn.

Badge Count Demo

  • Nếu một cấp độ nào đó có một số gợi ý số hiển thị và ở cấp độ sâu hơn có nhiều số gợi ý khácVSBET, thì số trong cấp độ hiện tại nên bằng tổng của các số ở cấp độ sâu hơn. Ví dụ như trong hình minh họa, số tin nhắn là 5, và nó chính xác bằng tổng của hai số nhỏ hơn ở cấp độ sâu hơn, cụ thể là 4 + 1. Điều này cho thấy sự liên kết chặt chẽ giữa các cấp độ và cách chúng bổ sung cho nhau để tạo ra một tổng hợp hoàn chỉnh.
  • Nếu một cấp độ cụ thể có thông báo bằng số (biểu tượng chấm đỏ) và ở cấp độ sâu hơn có cả số lẫn biểu tượng chấm đỏkết quả bóng đá ngoại hạng anh, thì ở cấp độ hiện tại sẽ ưu tiên hiển thị theo số. Tuy nhiên, nếu ở cấp độ sâu hơn không còn số nào mà chỉ còn biểu tượng chấm đỏ, thì ở cấp độ này mới ưu tiên hiển thị theo chấm đỏ. Ví dụ như trong hình chụp màn hình của ứng dụng dưới đây, khi chỉ còn thông báo tin nhắn hệ thống và nó được biểu thị bằng chấm đỏ, thì tab thứ hai cũng sẽ hiển thị thành chấm đỏ để phản ánh điều đó. Trong trường hợp khác, nếu người dùng tiếp tục thao tác và tất cả các số trên các tab đều bị xóa sạch, chỉ còn lại biểu tượng chấm đỏ, điều này cho phép người dùng dễ dàng nhận biết tab nào cần chú ý mà không cần phải kiểm tra kỹ lưỡng nội dung bên trong. Điều này đặc biệt hữu ích khi bạn đang quản lý nhiều thông tin phức tạp hoặc khi bạn cần nhanh chóng xác định tab nào cần hành động ngay lập tức.

Badge Dot Demo

Bạn có thể thấy rằng những điểm tóm tắt trên đây khá tương đồng với logic hiển thị của hầu hết các ứng dụng. Dù có một số khác biệt nhỏkết quả bóng đá ngoại hạng anh, nhưng điều đó không làm ảnh hưởng nhiều đến phần thảo luận tiếp theo của chúng ta. Những điểm khác biệt ấy thường chỉ là những chi tiết kỹ thuật mà người dùng cuối cùng ít khi để ý đến. Điều quan trọng là chúng ta vẫn có thể hiểu rõ được cấu trúc cơ bản và cách hoạt động chung của ứng dụng.

Bình luận đã nhận

Khi chỉ tập trung phân tích logic hiển thị chấm đỏ trên tab "Tin nhắn"boi tu vi, chúng ta có thể dễ dàng viết ra mã nguồn giả (pseudo-code) giống như bên dưới: ```plaintext function capNhatChamDo(tongSoTinNhanMoi) { if (tongSoTinNhanMoi > 0) { hienThiChamDo(); neu (tongSoTinNhanMoi >= 99) { hienThiSo(99); } else { hienThiSo(tongSoTinNhanMoi); } } else { anChamDo(); } } function xuLyClickTabTinNhan() { neu ( dangHienThi) { resetSoTinNhanMoi(); capNhatChamDo(0); } else { // Xử lý khi người dùng chuyển sang tab tin nhắn } } ``` Trên đây là cách thiết kế logic cơ bản để quản lý việc hiển thị chấm đỏ trên tab "Tin nhắn". Code này giúp cập nhật giao diện dựa trên số lượng tin nhắn chưa đọc và sẽ ẩn chấm đỏ khi người dùng chuyển đến tab này.

							
								
1
2
3
4
5
6
7
8
9
10
													
														int
													 count
													 =
													 Số lượng bình luận +
													 Số lượt thích;
													
if
													 (
													count
													 >
													 0
													)
													 {
													
	Hiển thị số lượng count
}
													
else
													 if
													 (
													Có thông báo hệ thống)
													 {
													
	Hiển thị thông báo đỏ
}
													
else
													 {
													
	Ẩn số và thông báo đỏ
}
													

Mã nguồn này chắc chắn có thể đáp ứng được yêu cầuVSBET, nhưng nhược điểm của nó cũng khá rõ ràng. Điểm quan trọng nhất là nó đòi hỏi logic hiển thị trong tab "Tin nhắn" phải liệt kê tất cả các loại tin nhắn con (như bình luận, thích, tin hệ thống) và phải phân biệt rõ ràng từng loại là số hay dấu chấm đỏ. Những gì đã được trình bày ở trên chỉ áp dụng cho trường hợp hai cấp độ trang, còn nếu xuất hiện thêm các cấp độ thứ ba hoặc nhiều hơn nữa thì làm sao? Những thông tin này sẽ cần phải lặp đi lặp lại ở mọi cấp độ trang khác nhau, điều đó vừa phức tạp vừa dễ gây lỗi.

Việc này sẽ khiến việc bảo trì và chỉnh sửa trở nên phức tạp hơn. Hãy tưởng tượng rằngboi tu vi, dưới mục "tin nhắn" lại thêm một loại tin nhắn mới, hoặc một loại tin nhắn nào đó thay đổi cách hiển thị từ dạng số thành biểu tượng chấm đỏ, thậm chí là một loại tin nhắn nào đó được di chuyển từ ngăn xếp trang này sang ngăn xếp trang khác. Tất cả những trường hợp như vậy đều yêu cầu tất cả các trang ở cấp cao hơn phải thực hiện điều chỉnh tương ứng. Khi ứng dụng có ngày càng nhiều loại tin nhắn, lên đến vài chục loại, có thể tưởng tượng rằng việc chỉnh sửa này rất dễ dẫn đến sai sót. Thêm vào đó, khi số lượng tin nhắn tăng lên, việc quản lý chúng không chỉ khó khăn mà còn có thể gây ra sự chồng chéo trong logic của ứng dụng. Điều này có thể dẫn đến tình trạng một số tính năng bị lỗi hoặc hoạt động không ổn định nếu không được kiểm tra kỹ lưỡng trước khi triển khai. Chính vì thế, việc thiết kế hệ thống cần có chiến lược rõ ràng để tránh những rủi ro không đáng có trong quá trình phát triển.

Cách quản lý số và thông báo đỏ dựa trên mô hình cây

Những vấn đề ở trênboi tu vi, chúng tôi đã xử lý trong MicroLove Trong giai đoạn đầu phát triển ứng dụngkết quả bóng đá ngoại hạng anh, chúng tôi cũng đã gặp phải một số vấn đề. Sau đó, chúng tôi quyết định tái đánh giá cấu trúc của các biểu tượng đỏ và số liệu hiển thị trong ứng dụng, chuyển sang cách nhìn nhận theo dạng cây (tree structure). Điều này đã giúp cho công tác bảo trì trở nên dễ dàng hơn rất nhiều. Không chỉ vậy, việc áp dụng phương pháp mới còn giúp đội ngũ phát triển có cái nhìn toàn diện hơn về cách hoạt động của từng thành phần trong ứng dụng.

Một trang ứng dụng vốn dĩ đã có thứ bậckết quả bóng đá ngoại hạng anh, về bản chất đường dẫn truy cập trang chính là cấu trúc cây.

Biểu đồ cấu trúc cây Badge Number

Như đã trình bày trong hình trênkết quả bóng đá ngoại hạng anh, nút 1 đại diện cho trang cấp 1, trang này có chứa ba lối vào trang cấp 2, tương ứng với các nút 2, 3 và 4. Nếu đi sâu thêm một cấp nữa, chúng ta sẽ đến các trang đích cuối cùng, được biểu thị bằng các nút hình vuông màu xanh lá cây. Những trang đích này là điểm kết thúc của hệ thống phân cấp, nơi người dùng có thể thực hiện các hành động cụ thể hoặc thu thập thông tin chi tiết từ cấu trúc này.

Mô hình cây này có thể được trình bày như sau:

  • Các nút lá (các nút hình vuông màu xanh lá cây) đại diện cho trang cuối cùng nơi tin nhắn sẽ được hiển thị. Cách thức mà tin nhắn được thể hiện tại các nút lá đã được xác định từ giai đoạn thiết kế sản phẩm. Chẳng hạnboi tu vi, nó có thể trực tiếp hiển thị nội dung tin nhắn hoặc chỉ hiển thị một con số trước, sau đó người dùng phải nhấp vào để xem chi tiết nội dung (giống như thông báo số lượng bình luận trong các ảnh chụp màn hình ứng dụng trước đây), hoặc thậm chí bật hộp thoại để thông báo. Tóm lại, cách trình bày này đã được mã hóa và cố định trong hệ thống logic nghiệp vụ của sản phẩm.
  • Các nút trung gian (những nút hình tròn màu cam) đại diện cho các trang nằm trên hành trình từ trang cấp 1 đến trang đích của tin nhắn. Thường thì những gì hiển thị trên các nút trung gian là số hoặc chấm đỏ để thể hiện sự thông báo.
  • Mỗi loại tin nhắnboi tu vi, chúng tôi gọi là mộ Nó có ba thuộc tính:
    • type: Loại Badge Number.
    • count: Đếm số lượngVSBET, mỗi Badge Number cho mỗi người dùng sẽ có một giá trị đếm riêng.
    • Cách hiển thị badge number hiện tại trên nút cha: 0 đại diện cho biểu tượng chấm đỏVSBET, trong khi 1 thể hiện dạng số.
  • Dựa trên loại hình dịch vụ mà nó thuộc vềVSBET, số hiệu huy hiệu (Badge Number) sẽ được phân vào các danh mục lớn (Category) khác nhau. Trong mỗi danh mục lớn này, các loại số hiệu huy hiệu sẽ được phân bổ trong cùng một khoảng loại (type). Ví dụ như trong sơ đồ cây cấu trúc ở trên, các nút 2, 3 và 4 lần lượt đại diện cho ba loại hình dịch vụ, tức là ba danh mục lớn, với các khoảng loại tương ứng là [A, C], [X, Y], [R, T]. Để đưa ra ví dụ thực tế hơn, hãy lấy mạng xã hội WeChat làm ví dụ. Trong danh mục lớn của trang (Friends' Circle), các loại số hiệu huy hiệu bao gồm: ai đó đã bình luận bài viết của tôi (số), ai đó đã thích bài viết của tôi (số), bạn bè có bài viết mới (biểu tượng chấm đỏ), v.v. Các danh mục lớn này không chỉ giúp người dùng dễ dàng nhận biết các loại thông báo mà còn tạo điều kiện cho hệ thống quản lý thông tin một cách khoa học và hiệu quả. Điều này đặc biệt quan trọng trong môi trường giao tiếp trực tuyến phức tạp, nơi mà số lượng thông tin cần được phân loại và xử lý hàng ngày là vô cùng lớn.

Để biểu diễn Badge Number của một nhóm lớn bằng một khoảng giá trị loạiboi tu vi, khi gán giá trị cho các loại, chúng ta có thể áp dụng cách tiếp cận như sau: sử dụng một số nguyên (int) để đại diện cho loại Badge Number, trong đó 16 bit cao sẽ biểu thị nhóm lớn. Ví dụ, nếu nhóm "Tin nhắn" có giá trị 16 bit cao là 0x2, thì ba loại Badge Number thuộc nhóm này có thể được phân bổ như sau: - Loại thứ nhất: 0x20001 - Loại thứ hai: 0x20002 - Loại thứ ba: 0x20003 Cách làm này không chỉ giúp quản lý dễ dàng hơn mà còn tạo ra sự linh hoạt và hiệu quả trong việc phân loại cá

  • Nhận được bình luận: (0x2 « 16) + 0x1
  • Nhận được lượt thích: (0x2 « 16) + 0x2
  • Thông báo hệ thống: (0x2 « 16) + 0x3

Thế làkết quả bóng đá ngoại hạng anh, nhóm "tin nhắn" có thể được biểu thị bằng một khoảng kiểu dữ liệu [(0x2 << 16) + 0x1, (0x2 << 16) + 0x3]. Đây là cách gọn gàng để phân loại và quản lý các thông tin quan trọng trong hệ thống. Khoảng giá trị này giúp xác định rõ ràng ranh giới cho các loại tin nhắn, từ đó dễ dàng theo dõi và xử lý hơn khi triển khai các ứng dụng phức tạp.

Sau khi có các khoảng loại trừboi tu vi, hãy cùng xem lại các nút trung gian trong mô hình cây. Tất cả chúng đều có thể được biểu diễn bằng một hoặc nhiều khoảng loại trừ. Cách chúng được hiển thị (số, chấm đỏ hay ẩn đi) phụ thuộc vào việc tính tổng tất cả các khoảng loại trừ của cây con tương ứng. Quy trình tính toán cụ thể như sau: Đầu tiên, ta cần duyệt qua từng cây con liên kết với nút trung gian đó. Mỗi khoảng loại trừ trong cây con sẽ được thêm vào một danh sách tạm thời. Nếu có sự trùng lặp giữa các khoảng loại trừ, chúng sẽ được hợp nhất thành một khoảng lớn hơn. Tiếp theo, sau khi đã tổng hợp toàn bộ khoảng loại trừ từ tất cả các cây con, chúng ta kiểm tra điều kiện để xác định cách thức hiển thị nú Nếu tổng khoảng loại trừ bao phủ toàn bộ phạm vi giá trị, nút sẽ được ẩn đi. Nếu chỉ một phần nào đó của phạm vi bị che khuất, nút sẽ được hiển thị dưới dạng chấm đỏ. Cuối cùng, nếu không có khoảng nào bị che lấp, nó sẽ hiển thị dưới dạng số. Quy trình này giúp đảm bảo rằng cấu trúc cây luôn phản ánh logic chính xác và nhất quán đối với tất cả các loại dữ liệu.

  • Trước tiênkết quả bóng đá ngoại hạng anh, hãy cộng tất cả các loại số trong khoảng loại, nếu lớn hơn 0 thì hiển thị số; nếu không,
  • Tiếp theoVSBET, cộng tất cả các loại thông báo đỏ trong khoảng loại, nếu lớn hơn 0 thì hiển thị thông báo đỏ; nếu không,
  • Ẩn số và thông báo đỏ.

Thực hiện mã hóa mô hình cây

Thực hiện mô hình câykết quả bóng đá ngoại hạng anh, chúng tôi gọi là Bài viết này cung cấp một phiên bản Demo cho Android, mã nguồn có thể được tải xuống từ GitHub: https://github.com/tielei/BadgeNumberTree

Bây giờ chúng ta cùng phân tích phần quan trọng.

Trong phiên bản Androidkết quả bóng đá ngoại hạng anh, lớp thực hiện chính được gọi là Dưới đây là đoạn mã quan trọng của nó (để không làm gián đoạn việc hiểu logic chính, các đoạn mã không cần thiết đã bị lược bỏ và không được hiển thị ở đây. Nếu bạn muốn xem toàn bộ mã nguồn, vui lòng truy cập GitHub để tải về).

							
								
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
													/**
public
													 interface
													 AsyncResult
													<
													ResultType
													>
													 {
													
    void
													 returnResult
													(
													ResultType
													 result
													);
													
}
													

/**
public
													 class
													 BadgeNumberTreeManager
													 {
													
    /** * Thiết lập số badge * @param badgeNumber Số badge cần được thiết lập * @param asyncResult Kết quả trả về từ hoạt động bất đồng bộ. Kết quả này sẽ là một giá trị booleanVSBET, cho biết liệu việc thiết lập có thành công hay không. */
    public
													 void
													 setBadgeNumber
													(
													final
													 BadgeNumber
													 badgeNumber
													,
													 final
													 AsyncResult
													<
													Boolean
													>
													 asyncResult
													)
													 {
													
        ...
													
    }
													

    /** * Tính tổng số badge number * @param badgeNumber Số badge cần được cộng dồn * @param asyncResult Kết quả trả về từ hoạt động bất đồng bộ. Kết quả này sẽ là một giá trị Booleanboi tu vi, cho biết liệu thao tác cộng dồn có thành công hay không. */
    public
													 void
													 addBadgeNumber
													(
													final
													 BadgeNumber
													 badgeNumber
													,
													 final
													 AsyncResult
													<
													Boolean
													>
													 asyncResult
													)
													 {
													
        ...
													
    }
													

    /** * Xóa badge number theo loại đã chỉ định * @param type Loại badge number cần được xóa. * @param asyncResult Kết quả trả về từ hoạt động xử lý bất đồng bộ. Kết quả này sẽ là một giá trị Booleankết quả bóng đá ngoại hạng anh, cho biết việc xóa có thành công hay không. */
    public
													 void
													 clearBadgeNumber
													(
													final
													 int
													 type
													,
													 final
													 AsyncResult
													<
													Boolean
													>
													 asyncResult
													)
													 {
													
        ...
													
    }
													

    /** * Lấy số hiệu badge theo loại được chỉ định * @param type Loại. Khi muốn lấy số hiệu badge từ cuộc trò chuyệnboi tu vi, chỉ cần truyền giá trị 0. * @param asyncResult Kết quả trả về bất đồng bộ, sẽ cung cấp số lượng count của số hiệu badge theo loại được chỉ định. */
    public
													 void
													 getBadgeNumber
													(
													final
													 int
													 type
													,
													 final
													 AsyncResult
													<
													Integer
													>
													 asyncResult
													)
													 {
													
        ...
													
    }
													

    /** * Dựa trên danh sách khoảng cách loại badge để tính toán tổng số badge của một nút cha trong cấu trúc cây. * Thứ tự ưu tiên sẽ là các con số trướcVSBET, tiếp theo mới đến các dấu chấm đỏ. * Trong thực tế, mỗi danh sách khoảng cách loại badge tương ứng với một nút cha trong cây cấu trúc. * @param danhSachKhoangCachLoaiBadge Danh sách khoảng cách loại badge được chỉ định, chắc chắn chứa ít nhất một khoảng. * @param ketQuaAsyc Kết quả trả về từ xử lý bất đồng bộ, nó sẽ cung cấp thông tin tình trạng badge theo loại (bao gồm cả cách hiển thị và tổng số lượng). */
    public
													 void
													 getTotalBadgeNumberOnParent
													(
													final
													 List
													<
													BadgeNumberTypeInterval
													>
													 typeIntervalList
													,
													 final
													 AsyncResult
													<
													BadgeNumberCountResult
													>
													 asyncResult
													)
													 {
													
        // Đầu tiên tính toán loại badge number để hiển thị số
        getTotalBadgeNumberOnParent
													(
													typeIntervalList
													,
													 BadgeNumber
													.
													DISPLAY_MODE_ON_PARENT_NUMBER
													,
													 new
													 AsyncResult
													<
													BadgeNumberCountResult
													>()
													 {
													
            @Override
													
            public
													 void
													 returnResult
													(
													BadgeNumberCountResult
													 result
													)
													 {
													
                if
													 (
													result
													.
													getTotalCount
													()
													 >
													 0
													)
													 {
													
                    // Tổng số loại số lớn hơn 0kết quả bóng đá ngoại hạng anh, có thể trả về rồi.
                    if
													 (
													asyncResult
													 !=
													 null
													)
													 {
													
                        asyncResult
													.
													returnResult
													(
													result
													);
													
                    }
													
                }
													
                else
													 {
													
                    // Tổng số loại số không lớn hơn 0boi tu vi, tiếp tục tính toán loại thông báo đỏ
                    getTotalBadgeNumberOnParent
													(
													typeIntervalList
													,
													 BadgeNumber
													.
													DISPLAY_MODE_ON_PARENT_DOT
													,
													 new
													 AsyncResult
													<
													BadgeNumberCountResult
													>()
													 {
													
                        @Override
													
                        public
													 void
													 returnResult
													(
													BadgeNumberCountResult
													 result
													)
													 {
													
                            if
													 (
													asyncResult
													 !=
													 null
													)
													 {
													
                                asyncResult
													.
													returnResult
													(
													result
													);
													
                            }
													
                        }
													
                    });
													
                }
													
            }
													
        });
													
    }
													


    private
													 void
													 getTotalBadgeNumberOnParent
													(
													final
													 List
													<
													BadgeNumberTypeInterval
													>
													 typeIntervalList
													,
													 final
													 int
													 displayMode
													,
													 final
													 AsyncResult
													<
													BadgeNumberCountResult
													>
													 asyncResult
													)
													 {
													
        final
													 List
													<
													Integer
													>
													 countsList
													 =
													 new
													 ArrayList
													<
													Integer
													>(
													typeIntervalList
													.
													size
													());
													
        for
													 (
													BadgeNumberTypeInterval
													 typeInterval
													 :
													 typeIntervalList
													)
													 {
													
            getBadgeNumber
													(
													typeInterval
													.
													getTypeMin
													(),
													 typeInterval
													.
													getTypeMax
													(),
													 displayMode
													,
													 new
													 AsyncResult
													<
													Integer
													>()
													 {
													
                @Override
													
                public
													 void
													 returnResult
													(
													Integer
													 result
													)
													 {
													
                    countsList
													.
													add
													(
													result
													);
													
                    if
													 (
													countsList
													.
													size
													()
													 ==
													 typeIntervalList
													.
													size
													())
													 {
													
                        // Tất cả các loại khoảng count đã có
                        int
													 totalCount
													 =
													 0
													;
													
                        for
													 (
													Integer
													 count
													 :
													 countsList
													)
													 {
													
                            if
													 (
													count
													 !=
													 null
													)
													 {
													
                                totalCount
													 +=
													 count
													;
													
                            }
													
                        }
													

                        // Trả về tổng
                        if
													 (
													asyncResult
													 !=
													 null
													)
													 {
													
                            BadgeNumberCountResult
													 badgeNumberCountResult
													 =
													 new
													 BadgeNumberCountResult
													();
													
                            badgeNumberCountResult
													.
													setDisplayMode
													(
													displayMode
													);
													
                            badgeNumberCountResult
													.
													setTotalCount
													(
													totalCount
													);
													
                            asyncResult
													.
													returnResult
													(
													badgeNumberCountResult
													);
													
                        }
													
                    }
													
                }
													
            });
													
        }
													
    }
													

    private
													 void
													 getBadgeNumber
													(
													final
													 int
													 typeMin
													,
													 final
													 int
													 typeMax
													,
													 final
													 int
													 displayMode
													,
													 final
													 AsyncResult
													<
													Integer
													>
													 asyncResult
													)
													 {
													
         ...
													
   }
													


    /**
    public
													 static
													 class
													 BadgeNumberTypeInterval
													 {
													
        private
													 int
													 typeMin
													;
													
        private
													 int
													 typeMax
													;
													

        public
													 int
													 getTypeMin
													()
													 {
													
            return
													 typeMin
													;
													
        }
													

        public
													 void
													 setTypeMin
													(
													int
													 typeMin
													)
													 {
													
            this
													.
													typeMin
													 =
													 typeMin
													;
													
        }
													

        public
													 int
													 getTypeMax
													()
													 {
													
            return
													 typeMax
													;
													
        }
													

        public
													 void
													 setTypeMax
													(
													int
													 typeMax
													)
													 {
													
            this
													.
													typeMax
													 =
													 typeMax
													;
													
        }
													
    }
													

    /** * Số hiệu huy hiệu được tính toán dựa trên một khoảng loại và cho ra kết quả tương ứng. */
    public
													 static
													 class
													 BadgeNumberCountResult
													 {
													
        private
													 int
													 displayMode
													;
													
        private
													 int
													 totalCount
													;
													

        public
													 int
													 getDisplayMode
													()
													 {
													
            return
													 displayMode
													;
													
        }
													

        public
													 void
													 setDisplayMode
													(
													int
													 displayMode
													)
													 {
													
            this
													.
													displayMode
													 =
													 displayMode
													;
													
        }
													

        public
													 int
													 getTotalCount
													()
													 {
													
            return
													 totalCount
													;
													
        }
													

        public
													 void
													 setTotalCount
													(
													int
													 totalCount
													)
													 {
													
            this
													.
													totalCount
													 =
													 totalCount
													;
													
        }
													
    }
													
    
}
													

Trong đoạn mã nàyboi tu vi, điểm cần chú ý bao gồm:

  • Trước đây đã đề cập đến bốn thao tác cơ bản đối với Badge Number: setBadgeNumberboi tu vi, addBadgeNumber, clearBadgeNumber và Tất cả những thao tác này đều khá đơn giản, và đoạn mã thực hiện chúng không được trình bày ở đây. Trên thực tế, trong Demo, chúng đã được triển khai dựa trên SQLite để lưu trữ dữ liệu offline. Điều quan trọng cần lưu ý là mỗi thao tác có thể được áp dụng trong những ngữ cảnh khác nhau: - **setBadgeNumber**: Thích hợp khi bạn muốn thiết lập một giá trị Badge Number cố định cho một mục cụ thể. - **addBadgeNumber**: Phù hợp hơn khi bạn muốn tăng giá trị Badge Number hiện tại của mục đó lên một giá trị mới. - **clearBadgeNumber**: Tương tự như việc xóa thông tin, nó thường được sử dụng khi bạn muốn xóa toàn bộ dữ liệu liên quan đế - **getBadgeNumber**: Đây là thao tác đọc giá trị hiện tại của Badge Number, rất hữu ích khi bạn cần hiển thị hoặc kiểm tra giá trị này trong giao diện người dùng. Việc hiểu rõ các trường hợp sử dụng sẽ giúp bạn tối ưu hóa hiệu suất cũng như cải thiện khả năng quản lý dữ liệu của ứng dụng một cách hiệu quả.
    • Hàm setBadgeNumber được sử dụng để thông báo chung về tin nhắn mới và sẽ được gọi khi có tin nhắn mới xuất hiệnboi tu vi, lưu trữ số lượng badge (huy hiệu) vào bộ nhớ cục bộ. Trong đó, giá trị count trong các huy hiệu này sẽ do máy chủ quản lý, vì vậy cần dựa vào dữ liệu từ máy chủ làm chuẩn. Mỗi lần nhận được dữ liệu từ máy chủ, hàm setBadgeNumber sẽ được kích hoạt để ghi đè lên giá trị đã lưu trước đó trong thiết bị.
    • Hàm addBadgeNumber được sử dụng để quản lý thông báo bằng cách đếm số lượng tin nhắn nhận được một cách cục bộVSBET, chẳng hạn như các tin nhắn trò chuyện. Đối với mỗi tin nhắn mới mà người dùng nhận được, hệ thống sẽ dựa vào việc tính toán số lượng cục bộ để cập nhật thông báo. Do đó, hàm addBadgeNumber đóng vai trò quan trọng trong việc tăng dần giá trị đếm này, giúp người dùng dễ dàng theo dõi số lượng tin nhắn chưa đọc của mình.
    • clearBadgeNumber được sử dụng để xóa số lượng badge của một loại cụ thể. Thông thườngkết quả bóng đá ngoại hạng anh, khi người dùng đã đọc hết tin nhắn mới trên trang tổng hợp tin nhắn (các nút lá cây), việc cần làm là xóa số lượng badge đi để cập nhật trạng thái. Điều này giúp giao diện luôn phản ánh đúng tình hình và tránh gây nhầm lẫn cho người dùng.
    • hàm getBadgeNumber được sử dụng để lấy giá trị số hiệu badge theo loại đã chỉ định. Hàm này thường được gọi khi hiển thị thông báo trên trang terminal của tin nhắnVSBET, đặc biệt là tại các nút lá trong cấu trúc cây (tree nodes), nơi chứa thông tin cụ thể cho từng mục.
  • Cuối cùngVSBET, có một phương thức private getBadgeNumber, khác biệt so với các phương thức public đã được overload trước đó. Thay vì chỉ lấy số Badge của một loại cụ thể nào đó, phương thức này sẽ tính tổng số Badge có kiểu nằm trong khoảng [typeMin, typeMax] và hiển thị theo một cách nhất định (displayMode). Đây là nền tảng quan trọng để xác định cách trình bày số Badge tại các nút giữa. Mã nguồn thực tế cho phương thức này không được đưa ra ở đây, nhưng nó khá đơn giản. Trong demo, nó được thực hiện bằng cách sử dụng SQLite thông qua một thao tác sum để tính tổng số Badge cần thiết dựa trên điều kiện đã cho.
  • Phương pháp công khai `getTotalBadgeNumberOnParent` đóng vai trò quan trọng trong việc thực hiện logic hiển thị số lượng huy hiệu tại các nú Tham số đầu vào của phương pháp này là một danh sách các khoảng loại (typeIntervalList)VSBET, đại diện cho một nút trung gian cụ thể. Kết quả trả về của nó là một đối tượng `BadgeNumberCountResult`, có thể biểu diễn ba trạng thái hiển thị khác nhau: số, chấm đỏ (red dot) hoặc ẩn (không hiển thị). Cách hoạt động của phương pháp này là gọi đến một phương thức được tải trọng riêng tư khác, nơi nó lần lượt tính tổng giá trị số và chấm đỏ cho từng khoảng loại trong danh sách loại (đây chính là cách mà chúng ta đã đề cập trước đó để tính toán tổng hợp từ tất cả các phân nhánh con của nút trung gian).

Ví dụ về mã gọi getTotalBadgeNumberOnParent:

							
								
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
    BadgeNumberTypeInterval
													 typeInterval
													 =
													 new
													 BadgeNumberTypeInterval
													();
													
    typeInterval
													.
													setTypeMin
													(
													BadgeNumber
													.
													CATEGORY_NEWS_MIN
													);
													
    typeInterval
													.
													setTypeMax
													(
													BadgeNumber
													.
													CATEGORY_NEWS_MAX
													);
													

    List
													<
													BadgeNumberTypeInterval
													>
													 typeIntervalList
													 =
													 new
													 ArrayList
													<
													BadgeNumberTypeInterval
													>(
													1
													);
													
    typeIntervalList
													.
													add
													(
													typeInterval
													);
													

    BadgeNumberTreeManager
													.
													getInstance
													().
													getTotalBadgeNumberOnParent
													(
													typeIntervalList
													,
													 new
													 AsyncResult
													<
													BadgeNumberCountResult
													>()
													 {
													
        @Override
													
        public
													 void
													 returnResult
													(
													BadgeNumberCountResult
													 result
													)
													 {
													
            if
													 (
													result
													.
													getDisplayMode
													()
													 ==
													 BadgeNumber
													.
													DISPLAY_MODE_ON_PARENT_NUMBER
													 &&
													 result
													.
													getTotalCount
													()
													 >
													 0
													)
													 {
													
                // Hiển thị số
                showTabBadgeCount
													(
													tabIndex
													,
													 result
													.
													getTotalCount
													());
													
            }
													 else
													 if
													 (
													result
													.
													getDisplayMode
													()
													 ==
													 BadgeNumber
													.
													DISPLAY_MODE_ON_PARENT_DOT
													 &&
													 result
													.
													getTotalCount
													()
													 >
													 0
													)
													 {
													
                // Hiển thị thông báo đỏ
                showTabBadgeDot
													(
													tabIndex
													);
													
            }
													 else
													 {
													
                // Ẩn số và thông báo đỏ
                hideTabBadgeNumber
													(
													tabIndex
													);
													
            }
													
        }
													
    });
													

Một số lưu ý bổ sung về việc thực hiện

  • Trong chương trình demoVSBET, cơ sở dữ liệu của BadgeNumberTreeManager sử dụng SQLite. Tuy nhiên, vì BadgeNumberTreeManager được gọi interface một cách khá thường xuyên, nên trong quá trình triển khai, đã thêm vào một lớp cache bộ nhớ tạm thời ở giữa (chi tiết có thể tham khảo trên mã nguồn GitHub). Điều này giúp tăng tốc đáng kể hiệu suất truy xuất dữ liệu và cải thiện hiệu quả hoạt động tổng thể của hệ thống.
  • Sau khi nhận được số Badge mới theo một cách nào đóVSBET, ứng dụng sẽ lưu trữ nó vào bộ nhớ cục bộ bằng cách sử dụng các phương thức setBadgeNumber và addBadgeNumber của lớ Có nhiều cách khác nhau để ứng dụng có thể lấy được số Badge này. Một số cách phổ biến là thông qua kết nối dài hạn mà ứng dụng tự triển khai hoặc từ nền tảng bên thứ ba, trong đó dữ liệu được đẩy trực tiếp đến ứng dụng. Ngoài ra, số Badge cũng có thể được tải về thông qua dịch vụ HTTP, đây thường là giải pháp phù hợp cho các cảnh báo mới không yêu cầu tính thời gian thực cao.
  • Logic hiện thị và làm mới số lượng huy hiệu (Badge Number) tại các nút giữa (middleware nodes)kết quả bóng đá ngoại hạng anh, cụ thể là việc gọi đến phương thức getTotalBadgeNumberOnParent của BadgeNumberTreeManager, cần được thực thi ở mọi thời điểm bắt buộc. Dựa trên ví dụ Demo phiên bản Android được đề cập trong bài viết này, các thời điểm này bao gồm: khi trang Resume được kích hoạt, khi chuyển đổi giữa các tab con, và khi nhận được số lượng huy hiệu mới từ hệ thống. Nếu logic cập nhật hiện thị không chính xác hoặc bị thiếu sót ở một số thời điểm quan trọng, đây cũng thường là nguyên nhân phổ biến khiến biểu tượng số đỏ (digital red-dot) trong ứng dụng không hoạt động đúng như mong muốn.
  • Việc xóa giá trị của nút trung gian Badge Number thường có hai trường hợp phổ biến: (1) Chỉ khi tất cả các nút con đều được xóa thì nút trung gian mới bị xóa; (2) Bất kỳ khi nào người dùng nhấn vào nútVSBET, nó sẽ tự động bị xóa mà không quan tâm đến trạng thái của các nút con. Trong ví dụ Demo mà bài viết này cung cấp, cách thực hiện dựa trên trường hợp thứ nhất. Nếu muốn chuyển sang trường hợp thứ hai, cần bổ sung thêm một dấu hiệu riêng biệt cho từng nút trung gian, nhưng điều chỉnh này khá đơn giản và không quá phức tạp. Một số nhà phát triển có thể cân nhắc thêm tính năng này để cải thiện trải nghiệm người dùng, ví dụ như tạo một hộp kiểm nhỏ hoặc biến phụ đi kèm mỗi nút trung gian để lưu trữ thông tin về trạng thái xóa. Điều này giúp đảm bảo rằng mọi thao tác đều linh hoạt hơn, phù hợp với yêu cầu cụ thể của từng ứng dụng.
  • Mặc dù các ví dụ mã nguồn trong bài viết này được xây dựng dựa trên Android Javakết quả bóng đá ngoại hạng anh, nhưng mô hình cây (tree model) mà bài viết đề xuất hoàn toàn có thể áp dụng để triển khai trong các ứng dụng không sử dụng nền tả Điều này mở ra khả năng linh hoạt cho việc tái sử dụng mô hình dữ liệu này trong nhiều môi trường phát triển khác nhau, từ đó giúp các nhà phát triển dễ dàng tích hợp vào các hệ thống đa nền tảng hoặ

Bài viết gốcVSBET, vui lòng ghi rõ nguồn và bao gồm mã QR bên dưới! Nếu không, từ chối tái bản!
Liên kết bài viết này: /v8vru2kt.html
Hãy theo dõi tài khoản Weibo cá nhân của tôi: Tìm kiếm tên tôi "Trương Thiết Lệ" trên Weibo.
Tài khoản WeChat của tôi: tielei-blog (Trương Thiết Lệ)
Bài trước: Con gái và những cuốn sách tranh của cô ấy
Bài sau: Chi tiết về cấu trúc dữ liệu bên trong Redis (4) —— ziplist