5

Tôi có một số lớp con Hoạt động trong dự án của mình, mỗi lớp gọi một dịch vụ web dựa trên SOAP, xử lý và hiển thị kết quả. Soạn SOAP, xử lý cuộc gọi và phân tích kết quả thành các đối tượng POJO khác nhau được đóng gói trong lớp MyWebService. Lớp này thực thi (các) cuộc gọi dịch vụ web thực tế thông qua AsyncTask.Mẫu để sử dụng lại Android AsnycTask qua một số Hoạt động?

Để có thể trả lại kết quả cho lớp con Hoạt động gọi, tôi đã xác định rằng tất cả các hoạt động này nên triển khai giao diện WebServiceResultProcessor, xác định một hàm duy nhất (processWebServiceResults) hoạt động như gọi lại cho AsyncTask, được gọi từ onPostExecute .

Tôi cũng muốn hiển thị ProgressDialog trong khi gọi dịch vụ web. Và đây là câu hỏi của tôi. Để có thể hiển thị ProgressDialog (hoặc từ MyWebService hoặc AsyncTask), tôi cần chuyển tham chiếu đến Context của Activity của người gọi. Và để có thể thực hiện chức năng gọi lại từ AsyncTask, tôi cũng cần phải vượt qua cùng một tham chiếu đối tượng, nhưng lần này là một WebServiceResultProcessor. Điều này dường như với tôi một mùi mã, đi qua cùng một đối tượng hai lần, nhưng không thể nhìn thấy bất kỳ cách nào xung quanh đó. Thay vì giao tiếp, tôi có thể tạo một lớp cơ sở mới, mở rộng lớp Activity và thực thi thừa kế từ lớp mở rộng, nhưng điều đó có nghĩa là tôi sẽ loại trừ ListActivity và các thích sử dụng lớp MyWebService này.

Có cách nào tốt hơn để thực hiện việc này không?

+0

Liệu WebServiceResultProcessor của bạn mở rộng Context/Hoạt động? –

+0

@HeikoRupp no, và tôi có lẽ muốn giữ nó theo cách đó. –

Trả lời

0

Mặc dù cảnh báo của Arhimed, tôi đã sử dụng AsyncTask vì nó vẫn phù hợp với mục đích của tôi. Tôi chỉ đảm bảo rằng tất cả các Hoạt động gọi dịch vụ web, theo số onDestroy() của họ, gửi cancel() đến AsyncTask được gọi. Việc thực hiện AsyncTask chính nó xử lý một cách duyên dáng yêu cầu hủy bỏ bằng cách kiểm tra isCancelled() ở khắp mọi nơi khi cần thiết.

Đối với câu hỏi ban đầu, tôi phải có mất hiệu lực - giải pháp thực sự đơn giản.Tôi chuyển thể hiện của lớp con Hoạt động như là một đối tượng đến AsyncTask và đưa nó vào một trong hai ngữ cảnh hoặc tới WebServiceResultProcessor, nếu cần thiết. Những mảnh vỡ cho thấy cách hoạt động:

if (callerActivity instanceof Context) { 
    ProgressDialog dialog = new ProgressDialog((Context)callerActivity); 
} 

...

if (callerActivity instanceof WebServiceResultProcessor) { 
    ((WebServiceResultProcessor)callerActivity).processWebServiceResults(soapObject); 
} 
+1

Tôi nghĩ 'if (callerActivity instanceof Context) {..}' là một kiểm tra dự phòng. Trừ khi tôi đang thiếu bất cứ điều gì 'callerActivity' trong trường hợp của bạn sẽ luôn luôn là một thể hiện của' Context', vì vậy bạn có thể trực tiếp gọi mã tạo tiến trình. –

4

+1, một câu hỏi hay!

Đây không phải là câu trả lời trực tiếp cho câu hỏi của bạn. Tuy nhiên, hãy để tôi nói rằng tôi nghĩ rằng AsyncTask không phải là lựa chọn đúng đắn cho những thứ như vậy. Tôi nghĩ vậy vì trong trường hợp này, AsyncTask giữ một tham chiếu đến một số Activity (thông qua ProgressDialog bản sao hoặc gọi lại được gọi từ onPostExecute()).

Chỉ cần tưởng tượng: trong Android, hệ điều hành có thể giết Activity trước khi AsyncTask thực thi doInBackground(). Đây là, tất nhiên, một số loại trường hợp góc, nhưng nó không phải là không thể. Hãy xem xét một kịch bản: người dùng nhận được một cuộc gọi đến, hoạt động của bạn trở nên vô hình, hệ điều hành cần thêm RAM và do đó nó quyết định tiêu diệt hoạt động của bạn. Một trường hợp rò rỉ bộ nhớ, ít nhất.

Tôi không biết tại sao Google ẩn nghĩa là thông tin về cách giao diện người dùng phải được phân tách chính xác khỏi các tác vụ nền. Có, họ nói "sử dụng Dịch vụ". Nhưng nó không phải là một công việc tầm thường. Thật đáng tiếc là Google cung cấp hướng dẫn tốt đẹp cho hầu hết mọi chủ đề phát triển, nhưng không cung cấp cho chủ đề này. Tuy nhiên tôi có thể đề nghị kiểm tra bản trình bày "Google I/O 2010 - Android REST client applications" để lấy cảm hứng. Có vẻ như họ đã đưa ra một chìa khóa về cách thực hiện những việc như vậy trong Android.

+0

cảm ơn vì đã chỉ ra các mối nguy hiểm bằng cách sử dụng tham chiếu Ngữ cảnh từ bên trong AsyncTask. Tôi đã tìm thấy http://stackoverflow.com/questions/3357477/is-asynctask-really-conceptually-flawed-or-am-i-just-missing-câu hỏi và câu trả lời nào đó để đề cập đến chủ đề này khá rộng rãi. –

+0

@ András Szepesházi: cảm ơn, đó là một cuộc thảo luận thú vị. Tuy nhiên, họ chủ yếu thảo luận về cách thay đổi cấu hình workaround (ví dụ: hoạt động khởi động lại trên xoay thiết bị). Nhưng nếu hoạt động bị giết trong kịch bản được mô tả bởi tôi (cuộc gọi đến) trong khi có một asynctask tạo tài khoản người dùng mới trên máy chủ từ xa? :) Tài khoản sẽ được tạo, nhưng khi người dùng quay trở lại hoạt động, nó sẽ không bao giờ biết kết quả của asynctask. Vì vậy, người dùng sẽ thử lại và nhận được "tên người dùng đã được sử dụng" lỗi? :) Ok, nếu asycntask thực hiện giao dịch thanh toán thì sao? :) –

+0

wow đây là điều ác. Tôi rất muốn tránh sử dụng Dịch vụ và Người xử lý, nhưng có vẻ như đây là cách duy nhất để đi. –

3

Bạn có thể xem bài viết trên blog này (part 1part 2), triển khai dịch vụ web với AsyncTaskLoader và cùng một dịch vụ web với thành phần Dịch vụ. Hơn nữa nó cho thấy sự khác biệt giữa cả hai cách tiếp cận và cũng có những nhận xét thú vị cho bài báo.