Search code examples
androidandroid-asynctaskandroid-alertdialog

How to avoid application crashing when launching AlertDialog using AsyncTask() in ANDROID?


In an Android application, by clicking a button, in a fragment, I want to show an AlertDialog using AsynTask() method. I have put, in onPreExecute(), the function which called the AlertDialog. In doInBackground(), there is a task running, and in onPostExecute(), I dismiss the AlertDialog. The crash occurs just when I click the button. And it refers to line code in the LoadingDialog class, which is dialog.show();. I have tried many suggestions given on the site, but, the issue occurs again. Could anyone help me?

This is the LoadingDialog.java


    public class LoadingDialog {

    private Activity activity;
    private AlertDialog dialog;

    LoadingDialog(Activity myActivity){
        activity = myActivity;
    }

    public void startLoadingDialog(){
        AlertDialog.Builder builder = new AlertDialog.Builder(activity);

        LayoutInflater inflater = activity.getLayoutInflater();
        builder.setView(inflater.inflate(R.layout.custom_dialog, null));
        builder.setCancelable(false);

        dialog = builder.create();
        dialog.show();
    }

    public void dismissDialog(){
        dialog.dismiss();
    }
    }

This is my Fragment class


public class MyFragment extends Fragment {

    View view ;
    private Button btn_;
    private Activity activity;
    private AlertDialog dialog;
    private LoadingDialog loadingDialog;

    public MyFragment(){

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        this.view = inflater.inflate(R.layout.fragment_, container, false);

        loadingDialog = new LoadingDialog(getActivity());

        btn_ = this.view.findViewById(R.id._button);
        eventListnerReinitialiser();
        return this.view;
    }

    public void eventListnerReinitialiser() {
        this.btn_.setOnClickListener(v -> {
             new ShowDialogAsyncTask().execute();
        });
    }

    public class ShowDialogAsyncTask extends AsyncTask<Void, Void, Void> {
        int s = 0;
        @Override
        protected void onPreExecute() {
            loadingDialog.startLoadingDialog();
            super.onPreExecute();
        }
        @Override
        protected Void doInBackground(Void... params) {
            for(int i=0;i<1000000;i++)
                s = s + i;
            Toast.makeText(view.getContext(), "Valeur de s = "+ s, Toast.LENGTH_LONG).show() ;
            return null;
        }
        @Override
        protected void onPostExecute(Void result) {
            loadingDialog.dismissDialog();
            super.onPostExecute(result);
        }
    }

}

And I have this error log in my console of Android studio


    E/WindowManager: android.view.WindowLeaked: Activity com.example.myproject.Menu2Activity has leaked window DecorView@96c506[] that was originally added here
        at android.view.ViewRootImpl.<init>(ViewRootImpl.java:511)
        at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:338)
        at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:93)
        at android.app.Dialog.show(Dialog.java:322)

Solution

  • You are showing a toast in the doInBackground() of the AsyncTask, and this cannot be done. You can only update the Ui in the main thread.

    Showing the toast in the doInBackground() which is running in a background thread throws a exception and your fragment is forced to shutdown at that moment but the dialog is still open which caused the exception.

    So try calling the Toast.makeText(view.getContext(), "Valeur de s = "+ s, Toast.LENGTH_LONG).show() ; in the onPostExecute of AsyncTask.

    Here is how to do the AsyncTask part.

    public class ShowDialogAsyncTask extends AsyncTask<Void, Void, Void> {
            int s = 0;
            @Override
            protected void onPreExecute() {
                loadingDialog.startLoadingDialog();
                super.onPreExecute();
            }
            @Override
            protected Void doInBackground(Void... params) {
                for(int i=0;i<100_000_000;i++)
                    s = s + i;
    
                return null;
            }
            @Override
            protected void onPostExecute(Void result) {
                Toast.makeText(MainActivity.this, "Valeur de s = "+ s, Toast.LENGTH_LONG).show() ;
                loadingDialog.dismissDialog();
    
                super.onPostExecute(result);
            }
        }