简体   繁体   中英

ProgressDialog.show() - Activity has leaked window

I have created an AsyncTask class for all my background processes which require ProgressDialogs and put it in my Utils java class but when i try to call it, it has the described error on ProgressDialog's show() method.

Here is the AsyncTask class in Utils class:

public static class BackgroundTask extends AsyncTask<Void, Void, Void> {
    private WeakReference<Context> context;
    private ProgressDialog progressDialog;
    private String message;

    private Runnable doInBackground;

    public BackgroundTask(Context context, String message, Runnable doInBackground) {
        this.context = new WeakReference<>(context);
        this.message = message;
        this.doInBackground = doInBackground;

    }

    @Override
    protected void onPreExecute() {
        if (context == null)
            return;
        progressDialog = new ProgressDialog(context.get(), R.style.dialogStyle);
        progressDialog.setMessage(message);
        progressDialog.setCancelable(false);
        progressDialog.setCanceledOnTouchOutside(false);
        progressDialog.setIndeterminate(false);
        progressDialog.show();
    }

    @Override
    protected Void doInBackground(Void... params) {
        doInBackground.run();
        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        if(progressDialog != null)
            progressDialog.dismiss();
        progressDialog = null;
    }
}

And here is how i call it on MainActivity :

new Utils.BackgroundTask(this, "Loading...",() -> {
    // Something heavy to do
}).execute();

Whats the problem and how can i fix it. Thanks in advance.

Edit

Is there maybe a problem with loading fragment in activity? This is what i'm exactly calling in my MainActivity :

new Utils.BackgroundTask(this, "Loading...",() -> {
    String codeResponse = NetworkConnection.get(this, NetworkConnection.BaseUrl + "sms/code.php?mobile=0" + phoneNumber);
    if(codeResponse != null){
        this.code = new Gson().fromJson(codeResponse, CheckCodeModel.class).getCode();
        Toast.makeText(this, "Code is :" + code + ":", Toast.LENGTH_SHORT).show();

        FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
        transaction.replace(R.id.fl_login_fragmentHolder,new LoginCheckCodeFragment(),"CheckCode");
        transaction.addToBackStack("CheckCode");
        transaction.commit();
    }
}).execute();

For the correct use of WeakReferences, you need to check if the underlying value is null, not your weak reference object.

ie not:

if (context == null)  // this is always `false` as you instantiate in your constructor

but:

if (context.get() == null)

You might have spotted it yourself with a clearer variable name, perhaps using weakRefToContext rather than context .

Fixed it by putting part of my code in runOnUiThread() method:

new Utils.BackgroundTask(LoginActivity.this, "Loading...",() -> {
    String codeResponse = NetworkConnection.get(this, NetworkConnection.BaseUrl + "sms/code.php?mobile=0" + phoneNumber);
    if(codeResponse != null){
        runOnUiThread(() -> {
            this.code = new Gson().fromJson(codeResponse, CheckCodeModel.class).getCode();
            Toast.makeText(this, "Code is :" + code + ":", Toast.LENGTH_SHORT).show();

            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
            transaction.replace(R.id.fl_login_fragmentHolder,new LoginCheckCodeFragment(),"CheckCode");
            transaction.addToBackStack("CheckCode");
            transaction.commit();
        });
    }
}).execute();

Thanks to @Aman B. and @Blundell.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM