2013-08-18 37 views
11

Tôi đang xây dựng một ứng dụng Android giao tiếp với máy chủ thường xuyên miễn là ứng dụng đang chạy.Thực hành tốt nhất cho khách hàng Android để giao tiếp với máy chủ bằng cách sử dụng chủ đề

Tôi làm điều này bằng cách khởi xướng một kết nối đến máy chủ khi ứng dụng bắt đầu, sau đó tôi có một riêng biệt thread cho nhận tin nhắn gọi ReceiverThread, đây thread đọc tin nhắn từ socket, phân tích nó, và chuyển nó vào phần thích hợp của ứng dụng.

Điều này thread chạy trong một vòng lặp, đọc bất cứ điều gì nó đã đọc và sau đó chặn trên lệnh read() cho đến khi dữ liệu mới đến, do đó, nó dành phần lớn thời gian của nó bị chặn.

Tôi xử lý việc gửi thư qua một chuỗi khác, được gọi là SenderThread. Những gì tôi đang tự hỏi về là: tôi nên cấu trúc các SenderThread trong một thời trang tương tự? Có nghĩa là tôi nên duy trì một số hàng đợi cho chuỗi này, để cho nó gửi tất cả các tin nhắn trong hàng đợi và sau đó chặn cho đến khi tin nhắn mới nhập vào hàng đợi, hoặc tôi chỉ nên bắt đầu một chủ đề mới mỗi khi một tin nhắn cần được gửi đi , để cho nó gửi tin nhắn và sau đó "chết"? Tôi đang hướng tới cách tiếp cận đầu tiên, nhưng tôi không biết điều gì thực sự tốt hơn cả về mặt hiệu suất (giữ một luồng bị khóa trong bộ nhớ so với khởi tạo chủ đề mới) và về độ chính xác của mã.

Cũng vì tất cả các hoạt động của tôi cần có khả năng gửi và nhận tin nhắn tôi đang giữ tham chiếu đến cả hai chủ đề trong lớp Application của mình, đó có phải là phương pháp được chấp nhận hay không?

Một vấn đề tôi gặp phải với điều này là đôi khi nếu tôi đóng ứng dụng và chạy lại, tôi thực sự có hai phiên bản của ReceiveThread, vì vậy tôi nhận được một số thông báo hai lần.

Tôi đoán rằng điều này là do ứng dụng của tôi không thực sự đóng và chuỗi trước vẫn hoạt động (bị chặn trên hoạt động read()) và khi tôi mở lại ứng dụng, một chuỗi mới đã được khởi tạo, nhưng cả hai đều được kết nối với máy chủ để máy chủ gửi tin nhắn cho cả hai. Bất kỳ lời khuyên nào về cách giải quyết vấn đề này, hoặc về cách hoàn toàn sắp xếp lại nó sao cho nó sẽ đúng?

Tôi cố gắng nhìn lên những câu hỏi này nhưng không tìm thấy một số ví dụ mâu thuẫn cho câu hỏi đầu tiên của tôi, và không có gì là đủ hữu ích và áp dụng cho câu hỏi thứ hai của tôi ...

+0

"đóng cửa" các ứng dụng không thực sự giết chết nó. Nó chỉ tiếp tục chạy và đặc biệt là chủ đề là không có cách nào tự động dừng lại – zapl

+0

@ zapl có Tôi biết điều đó, đây là vấn đề của tôi. Câu hỏi đặt ra là: làm thế nào để ngăn chặn các sợi đáng tin cậy? HOẶC cách thực hiện cùng một ứng dụng tổng thể theo cách tránh được vấn đề này? – Bob

+0

Điều đó thực sự phức tạp. 'Thread # interrupt()' (+ 'Socket # close()') có thể được sử dụng để dừng nó nhưng phần cứng là theo dõi xem Ứng dụng có đang chạy hay không hoạt động ở chế độ nền. Mỗi hoạt động có thể làm điều đó từ 'onStart' trên' onStop' chẳng hạn. – zapl

Trả lời

17

1. cách tiếp cận của bạn là ok, nếu bạn thực sự cần giữ kết nối mở giữa máy chủ và ứng dụng mọi lúc mọi lúc. Tuy nhiên tôi sẽ sử dụng một kết nối không đồng bộ, như gửi một yêu cầu HTTP đến máy chủ và sau đó nhận được câu trả lời bất cứ khi nào máy chủ cảm thấy thích nó.

Nếu bạn cần máy chủ trả lời ứng dụng sau này, nhưng bạn không biết khi nào, bạn cũng có thể xem Google Cloud Messaging framework, cung cấp cho bạn cách gửi thông điệp nhỏ và minh bạch cho khách hàng của mình từ máy chủ của bạn.

Bạn cần cân nhắc một số điều, khi bạn đang phát triển một ứng dụng dành cho thiết bị di động.

  1. Điện thoại thông minh không có lượng pin vô tận.

  2. Kết nối Internet của điện thoại thông minh có phần dễ bay hơi và bạn sẽ mất kết nối Internet vào các thời điểm khác nhau.

Khi bạn giữ kết nối trực tiếp với máy chủ mọi lúc, ứng dụng của bạn tiếp tục gửi các gói dữ liệu còn sống, có nghĩa là bạn sẽ hút điện thoại khô nhanh. Khi kết nối Internet không ổn định như khi kết nối băng thông rộng di động, bạn sẽ mất kết nối đôi khi và cần khôi phục lại điều này. Vì vậy, nếu bạn sử dụng TCP vì bạn muốn đảm bảo rằng các gói của bạn được nhận, bạn có thể gửi lại các gói tương tự rất nhiều lần và vì vậy nhận được rất nhiều chi phí.

Ngoài ra, bạn có thể gặp vấn đề về luồng trên phía máy chủ, nếu bạn mở các chủ đề trên máy chủ của chính mình, điều đó có vẻ như vậy. Giả sử bạn có 200 khách hàng kết nối với máy chủ cùng một lúc. Mỗi khách hàng có 1 luồng mở trên máy chủ. Nếu máy chủ cần phục vụ 200 luồng khác nhau cùng một lúc, điều này có thể là một nhiệm vụ tiêu thụ hiệu suất cho máy chủ cuối cùng và bạn cũng sẽ cần phải làm rất nhiều công việc.

2. Khi bạn thoát khỏi ứng dụng của mình, bạn sẽ cần dọn dẹp sau khi bạn. Điều này nên được thực hiện theo phương pháp của bạn là Activity đang hoạt động.

Điều này có nghĩa là tiêu diệt tất cả các chuỗi đang hoạt động (hoặc ít nhất là làm gián đoạn), lưu trạng thái giao diện người dùng (nếu bạn cần) và xả và đóng bất kỳ kết nối mở nào đến máy chủ bạn có.

Theo như sử dụng Threads, tôi khuyên bạn nên sử dụng một số công cụ xây dựng sẵn trong luồng như Handlers hoặc triển khai AsyncTask.

Nếu bạn thực sự nghĩ rằng Thread là cách để đi, tôi chắc chắn sẽ khuyên bạn nên sử dụng Singleton pattern làm "người quản lý" cho luồng của bạn.

Người quản lý này sẽ kiểm soát chủ đề của bạn, vì vậy bạn không kết thúc với nhiều hơn một Thread nói chuyện với máy chủ tại bất kỳ thời điểm nào, ngay cả khi bạn đang ở một phần khác của ứng dụng.

Theo như các Application thi lớp đi, hãy nhìn vào các Application class documentation:

lớp cơ sở cho những người cần để duy trì trạng thái ứng dụng toàn cầu. Bạn có thể cung cấp việc triển khai của riêng bạn bằng cách chỉ định tên của nó trong thẻ AndroidManifest.xml của bạn, điều này sẽ khiến cho lớp đó được khởi tạo cho bạn khi quá trình cho ứng dụng/gói của bạn được tạo ra.

Thường không cần phải phân lớp Ứng dụng. Trong hầu hết các trường hợp, các trình đơn tĩnh có thể cung cấp chức năng tương tự theo cách mô đun hơn.

Vì vậy, giữ xa thực thi lớp Application của riêng bạn được khuyến khích, tuy nhiên nếu bạn để cho một trong Activities bạn khởi tạo lớp Singleton của riêng bạn để quản lý các Threads và kết nối bạn có thể (chỉ có thể) chạy vào rắc rối, bởi vì khởi tạo của singleton có thể "liên kết" với Activity cụ thể và vì vậy nếu cụ thể Activity bị xóa khỏi màn hình và bị tạm dừng, nó có thể bị giết và vì vậy singleton cũng có thể bị giết. Vì vậy, khởi tạo singleton bên trong triển khai Application của bạn có thể hữu ích.

Xin lỗi vì các bức tường của văn bản, nhưng câu hỏi của bạn là khá "bỏ ngỏ", vì vậy tôi đã cố gắng để cung cấp cho bạn một câu hỏi hơi mở - hy vọng nó sẽ giúp ;-)

+0

Cảm ơn bạn, mặc dù tôi vẫn chưa hoàn toàn chắc chắn về những gì chính xác để làm, câu trả lời của bạn đã giúp đỡ. Tôi biết rằng việc phát triển cho điện thoại di động có nhiều khía cạnh đối với nó như bảo tồn thời lượng pin, tuy nhiên tôi cần kết nối liên tục do trường hợp sử dụng ứng dụng của tôi. Việc sử dụng ứng dụng nên nói chung ngắn, 5 phút thường là quá đủ, tuy nhiên trong 5 phút đó, nhiều tương tác trên internet sẽ xảy ra. Tôi thực sự không nghĩ rằng giữ một kết nối còn sống trong 5 phút sẽ tiêu hao pin khô, phải không? – Bob

+0

@Bob 5 phút là tốt. Cập nhật thường xuyên trong nền là vấn đề. xem http://developer.android.com/training/efficient-downloads/index.html – zapl

Các vấn đề liên quan