簡體   English   中英

如何在Activity從Web服務請求SoapObject時實現ProgressDialog?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM