Android:进度对话框导致活动泄漏窗口?

4

我正在开发我的第一个Android应用程序,希望在用户单击登录按钮时显示进度对话框。因此,我将asynctask集成到应用程序中,所有操作如登录注销都已成功完成,但问题是成功登录后会出现错误,例如LoginActivity由于进度对话框而泄漏窗口。如何关闭进度对话框并更新UI。

请参考以下代码并告诉我需要做哪些更改:

以下是 LoginActivity:

public class LoginActivity extends SherlockActivity {
.................
@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    sessionmngr = new SessionManager(this);
    //check the user login or not
    if (sessionmngr.isLoggedIn()) {
        Intent checkLoginIntnt = new Intent(this,ProjectFragActivity.class);
        startActivity(checkLoginIntnt);
    }
    setContentView(R.layout.activity_login);
    ........
}
// onclick listener when click on login activity

public void LoginToBookingScape(View v) throws JSONException {

    username = edtTxtUserName.getText().toString();
    userpsw = edtTxtUserPsw.getText().toString();

    if ((username.trim().length() > 0)&&(userpsw.trim().length() > 0)) {

        JsonWebService jsonWebs = new JsonWebService();
        jsonWebs.execute(loginUrl);

    }else {
        ............
    }   
}

以下是LoginActivity中扩展AsyncTask的内部类。
private class JsonWebService extends AsyncTask<String,Void,String> {

    private ProgressDialog dialogLogin;
    @Override
    protected String doInBackground(String... url) {

                httpPost.setEntity(new UrlEncodedFormEntity(params));
                ....
                inStream = httpEntity.getContent();
                .........
                return jsonResp;
    }

    @Override
    protected void onPostExecute(String jsonData) {
        //get string data from doinBackground
        try {
            JSONObject jsonObj = new JSONObject(jsonData);
            String key_login = jsonObj.getString(KEY_LOGIN);

            if (key_login.equalsIgnoreCase("0")) {
                .............

            }else {
                ....
                sessionmngr = new SessionManager(getApplicationContext());

                sessionmngr.createLoginSession(id,jsonObj.getString(KEY_UNAME), 
                        jsonObj.getString(KEY_UEMAIL));

                dialogLogin = ProgressDialog.show(LoginActivity.this, "Bookingscape", 
                        "Please Wait",true);
                dialogLogin.setIcon(R.drawable.icon);
                new Thread(new Runnable() {

                    @Override
                    public void run() {
                        try {
                            Thread.sleep(4000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }).start();

                Intent inteProj = new Intent(getApplicationContext(),           

                    ProjectFragActivity.class);
                startActivity(inteProj);
                finish();   
            }
        ........
    }
    @Override
    protected void onCancelled() {
        dialogLogin.dismiss();
        dialogLogin = null;
        super.onCancelled();
    }
}

我希望在这里问一个问题:

以上代码是否优化并且可重用?

提前致谢!


通常情况下,您会在onPreExecute()中显示进度对话框,在doInBackground()中执行一些后台工作,并在onPostExecute()中关闭对话框并更新UI。 - Raghunandan
4个回答

11

问题在于你没有关闭进度对话框就要跳转到新的活动中,这会导致窗口泄漏错误。

我认为你必须将 dialogLogin.dismiss();onCancelled() 块移到代码的 onPostExecute 块中。

在去往另一个活动之前,你必须这样做。也就是在

Intent inteProj = new Intent(getApplicationContext(),ProjectFragActivity.class);
startActivity(inteProj);

这行代码,我认为可以解决你的问题。

有一个疑问: 你的onPreExecute在哪里?通常我会在那个块中显示进度条并在onPostExecute中关闭它。

通常流程如下:onPreExecute-->doInBackground --->onPostExecute

编辑:

onPreExecute:初始化您的UI组件(例如:Dialoges)。在您的情况下,ProgressDialog 显示出来。

doInBackground:控制会在 onPreExecute 块之后转到这里。这里 ProgressDialog 继续工作。

onPostExecute:所有后台操作完成后,控制将转到此处。在此处,您可以关闭 ProgressDialog 并转到新的活动。


@Nilesh 好的,我只是问一下,不用担心。这解决了你的问题吗? - edwin
Edwin,我在线程块中写了dialogLogin.dismiss()(Thread.sleep(4000)之后),但是出现了IllegalStateException:View not attached to the windowManager的错误。因此我将dialogLogin.dismiss()写在了onCanCelled方法中。如何解决这个问题? - Nilesh
@Nilesh 创建 onPreExecute 块并在其中初始化您的对话框。然后在 onPostExecute 中关闭它。 - edwin
当用户从第二个活动点击返回按钮时,用户应该返回到第二个活动,但它没有起作用。抱歉,实际上我不明白你的意思...你的意思是用户在按下返回键时不应再次回到登录页面吗? - edwin
@Nilesh 这样可以吗? - edwin
显示剩余6条评论

0
我也遇到了这个问题,原因如下。 我的应用程序接受输入并将其添加到SQLite数据库中。这是我的代码:
 public Item doInBackground(String...params) {
       Item item = new Item();
        try {

            item.setItemName(params[0]);
            item.setSupplierPhone(params[1]);
            ...
            databaseHandler.addItem(item);

            //Toast.makeText(mContext, "Item successfully saved.", Toast.LENGTH_SHORT).show();

            databaseHandler.close();


        } catch (SQLiteException e) {
            Toast.makeText(mContext, "Error saving Item!", Toast.LENGTH_SHORT).show();
        }
        return item;
    }

我认为这是因为在执行路径已经进入onPostExecute()之后尝试显示对话框。

值得注意的是,抛出此异常的原因有很多。其中许多在这里进行了讨论。


0

可能是因为你的写作方式

Intent inteProj = new Intent(getApplicationContext(),           
ProjectFragActivity.class);
startActivity(inteProj);

在关闭对话框之前,意味着您的对话框仍在显示进程,即使您的活动已更改。因此,请将您的

dialogLogin.dismiss();
dialogLogin = null;

这之前的行

Intent inteProj = new Intent(getApplicationContext(),           
ProjectFragActivity.class);
startActivity(inteProj);

那么这个问题就会得到解决。


0

在转到下一个活动之前,您需要关闭对话框。 使用: dialog.dismiss();


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接