[英]How to show a ProgressDialog while changing from a activity to another activity?
[英]How to implement a ProgressDialog while Activity requests a SoapObject from a Web Service?
我知道帶有Threads問題的ProgressDialog已被多次詢問,但沒有一個解決方案似乎適用於我的項目。 基本上我想要做的是:1)當用戶點擊一個按鈕時,Activity向服務器發送一個auth請求2)在完成此操作時會顯示ProgressDialog 3)當響應出現時我想要關閉ProgressDialog和Activity要讀取和解釋的返回對象
如果I:1)將Thread設置為使用響應更新Application字段,則下一個方法(在Thread之外)在訪問字段時拋出NPE 2)如果我在Thread中包含下一個方法,則第二個方法拋出'java.lang.RuntimeException:無法在未調用Looper.prepare()的線程內創建處理程序
很抱歉有一個很長的文字,但我完全失去了它...我的代碼是這樣的:
public class XXX extends Activity implements OnClickListener {
// (...)
private SoapObject returnObject;
private String response;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// (...)
authProgressDialog = ProgressDialog.show(XXX.this, "", "Authenticating...", true, false);
new Thread(new Runnable() {
@Override
public void run() {
authenticate(); // method that calls the API via SOAP
authenticateReal(); // method that handles the response
}
}).start();
mHandler = new Handler() {
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 10:
authProgressDialog.dismiss();
break;
}
}
};
}
}
public void authenticate() {
// API stuff (...)
AndroidHttpTransport aht = new AndroidHttpTransport(URL);
try {
aht.call(SOAP_ACTION, soapEnvelope);
returnObject = (SoapObject) soapEnvelope.getResponse();
response = returnObject.getProperty("ResponseStatus").toString();
}
catch (Exception e) {
e.printStackTrace();
}
finally {
mHandler.sendEmptyMessage(10);
}
}
// Method that needs to access returnObject and reponse objects and
// it is here where the NPE's or other exceptions are thrown
public void authenticateReal() {
// (...)
}
您最好使用AsyncTask
(這是Android方式):
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new TheTask().execute();
}
private class TheTask extends AsyncTask<Void, Void, Void>{
@Override
protected void onPreExecute() {
authProgressDialog = ProgressDialog.show(XXX.this, "", "Authenticating...", true, false);
}
@Override
protected Void doInBackground(Void... params) {
authenticate(); // method that calls the API via SOAP
authenticateReal(); // method that handles the response
return null;
}
@Override
protected void onPostExecute(Void result) {
authProgressDialog.dismiss();
}
}
順便說一下......我發現這個演示文稿非常有用(它討論了REST應用程序,但你可以為不同類型的應用程序應用相同的概念): 開發Android REST客戶端應用程序
對於你的上一個問題,請輸入“Looper.prepare();” 進入你的run()方法。
@Override
public void run() {
Looper.prepare();
authenticate(); // method that calls the API via SOAP
authenticateReal(); // method that handles the response
}
您是否檢查了authenticate()方法中的響應是否正常? (使用LogCat顯示響應)
否則,最好使用AsyncTask(如建議的那樣)。
如果你真的想使用Thread
而不是AsyncTask
你可以這樣試試:
public class XXX extends Activity implements OnClickListener {
...
private static int HANDLER_MESSAGE_AUTH_REQUEST_COMPLETE = 10;
...
private void performAuthentication(){
authProgressDialog = ProgressDialog.show(XXX.this, "", "Authenticating...", true, false);
Thread backgroundThread = new Thread() {
@Override
public void run() {
authenticate();
}
}
backgroundThread.start();
}
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch(msg.what){
case HANDLER_MESSAGE_AUTH_REQUEST_COMPLETE:
authProgressDialog.dismiss();
break;
}
}
}
private void authenticate(){
// existing authenticate code goes here
...
Message msg = Message.obtain();
msg.what = HANDLER_MESSAGE_AUTH_REQUEST_COMPLETE;
handler.sendMessage(msg);
// existing authenticateReal code goes here
...
}
}
從您的代碼中可以清楚地看出變量mHandler
分配給new Handler()
。 要清楚,在我的代碼中,這應該是class
本身的private
字段。 您還需要在authenticate()
方法中進行一些錯誤處理,以便在遇到錯誤時發送消息以關閉對話框。
正如其他人已經寫過的那樣,AsyncTask是繼續進行的方式。
但是:AsyncTask和Threads對UI元素有一些缺陷:
如果您更改了手機方向並且未在Manifest.xml中為您的Activity設置android:configChanges="keyboardHidden|orientation"
(意味着您必須自己處理onConfigChange),則方向更改將破壞並重新創建您的Activity和ContentView,同時斷開ProgressDialog與可見窗口的連接(它與舊窗口連接)。 Android不會殺死你的Thread或AsyncTask。 如果活動被銷毀,它也不會殺死它。 這些背景任務一直持續到完成為止。
嘗試解除()您的預先創建的ProgressDialog在ContentView被銷毀后拋出異常,因為它不再是您窗口的一部分。 在執行分離(異步)工作的情況下嘗試/捕獲LOT。 當你再次調用onPostExecute()時,你可能依賴的所有東西都可能已經消失或被不同的東西取代。 最后考慮注冊你在Activity中的某個Array中啟動的每個ASyncTask,並嘗試在Activity.onDestroy()中取消它們。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.