Как избежать сбоя приложения при запуске AlertDialog с использованием AsyncTask () в ANDROID? - PullRequest
2 голосов
/ 29 мая 2020

В приложении Android, нажав кнопку во фрагменте, я хочу показать AlertDialog с помощью метода AsynTask (). Я поместил в onPreExecute() функцию, которая вызвала AlertDialog. В doInBackground() выполняется задача, а в onPostExecute() я отклоняю AlertDialog. Cra sh возникает, когда я нажимаю кнопку. И это относится к коду строки в классе LoadingDialog, который равен dialog.show();. Я пробовал много предложений, представленных на сайте, но проблема возникает снова. Может ли кто-нибудь мне помочь?

Это 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();
    }
    }

Это мой класс фрагментов


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);
        }
    }

}

И у меня есть этот журнал ошибок в моей консоли Android студия


    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)

Ответы [ 2 ]

0 голосов
/ 29 мая 2020

В дополнение к тому, что также сказал Вивек:

  1. Измените ShowDialogAsyncTask на stati c class
  2. передайте диалог как WeakReference, затем используйте weakReference.get () в каждом месте где он используется
  3. Чтобы показать диалог, передайте context.getApplicationContext () как слабую ссылку.

В настоящее время ваша активность просачивается через AsyncTask.

0 голосов
/ 29 мая 2020

Вы показываете тост в doInBackground() AsyncTask, и это невозможно. Вы можете обновлять пользовательский интерфейс только в основном потоке.

Отображение тоста в doInBackground(), который выполняется в фоновом потоке вызывает исключение и ваш фрагмент принудительно завершается в этот момент, но диалоговое окно все еще открыто, что вызвало исключение.

Поэтому попробуйте вызвать Toast.makeText(view.getContext(), "Valeur de s = "+ s, Toast.LENGTH_LONG).show() ; в onPostExecute AsyncTask.

Вот как это сделать часть AsyncTask.

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);
        }
    }
...