La finestra di dialogo in attesa non funziona correttamente e l'app si blocca fino alla fine dell'attività

StackOverflow https://stackoverflow.com//questions/12716353

Domanda

Ho una classe che invia varie mail con allegati.

Poiché il metodo sendEmail(addresses); richiede il tempo di caricare gli allegati e inviare le e-mail, ho creato un asynctask per mostrare una finestra di dialogo d'attesa,

Tuttavia, sfortunatamente, durante l'invio dell'app si blocca fino a quando non ha terminato l'invio senza mostrare nulla (o talvolta mostra un avviso congelato per un piccolo istante prima della fine della procedura)

Le parti correlate del codice nella mia classe sono i seguenti

public class MyClass extends Activity {
    ...

    private ProgressDialog waitingDialog;

    ....

    OnClickListener mInvia = new OnClickListener() {
        public void onClick(View v) {
                new MyAsyncTaskClass().execute(new String[] {});
        }
    };

    public void prepareSending() {
        String x = "";
        for (String s : selectedMails) {
            x += (s + ";");
        }
        String[] addresses = x.split(";");
        sendEmail(addresses);
    }

    private void openFile() {
        Intent i = new Intent(Intent.ACTION_GET_CONTENT);
        i.setType("file/*");
        startActivityForResult(i, FILE_REQ_CODE);
    }

    protected void onActivityResult(int requestCode, int resultCode,
            Intent intentData) {

        Uri tmp = intentData.getData();
        filePath=getRealPath(tmp);
        super.onActivityResult(requestCode, resultCode, intentData);

    }


    public void sendEmail(String[] addresses) {

        Mail m = new Mail("sendermail@sample.com",
                "senderpassword");

        name = editor1.getText().toString();
        subject = editor2.getText().toString();
        text = editor3.getText().toString();
        emailReply = editor4.getText().toString();

        m.setTo(addresses);
        m.setFrom(emailReply);
        m.setSubject(subject);
        m.setBody(text + "\n\n\n Sent by" + name);
        try {
            m.send();
        } catch (Exception e) {
            Log.e("MyClass", "Cannot send email", e);
        }

        try {
            m.addAttachment(filePath);

            if (m.send()) {
                Alerts.Ok(MyClass.this);
                nSuccess++;
            } else {
                Alerts.ErrorSending(MyClass.this);
            }
        } catch (Exception e) {
            Alerts.ErrorAttachment(MyClass.this);
        }

    }

    //inner class that should show a waiting windows
    private class MyAsyncTaskClass extends AsyncTask<String, Void, Void> {

        @Override
        protected void onPreExecute() {
            waitingDialog = new ProgressDialog(MyClass.this);
            waitingDialog.setMessage("Loading ....");
            waitingDialog.setIndeterminate(true);
            waitingDialog.setCancelable(true);
            waitingDialog.show();
        }

        @Override
        protected Void doInBackground(final String... strings) {
            try {
                runOnUiThread(new Runnable() {
                    public void run() {
                        prepareSending();
                    }

                });
            } catch (Exception e) {

            }
            return null;
        }

        @Override
        protected void onPostExecute(Void params) {
            waitingDialog.dismiss();
        }
    }

    //end innerclass
    // start context menu code
    ......

}
.

È stato utile?

Soluzione

Problema

Wager è perché stai correndo tutto sul filo Ui:

    @Override
    protected Void doInBackground(final String... strings) {
        try {
            runOnUiThread(new Runnable() {
                public void run() {
                    prepareSending();
                }

            });
        } catch (Exception e) {

        }
        return null;
    }
.

fai questo invece!

Esegui tutto il tuo codice doInBackground basato su cose non-interfacciate.

    @Override
    protected Void doInBackground(final String... strings) {
        prepareSending();
        return null;
    }
.

Accesso all'UI

Se è necessario accedere ai dati dall'interfaccia utente, o per qualsiasi altra cosa sulla filettatura dell'interfaccia utente, fai questo prima .

    protected void onPreExecute() {
        // Find all your "editor" fields here, and save them to member variables within the AsyncTask.
        // ...
    }
.

quindi invia quelli al tuo metodo

in prepareSending e sendEmail accettano i dati come parametri:

public void prepareSending(String name, String subject, String text, String emailReply) {
    // ...
    sendEmail(addresses, name, subject, text, emailReply);
}
public void sendEmail(String[] addresses, String name, String subject, String text, String emailReply) {
    // ...
}
.

E infine, è necessario inviare quelli da doInBackground:

    @Override
    protected Void doInBackground(final String... strings) {
        prepareSending(mName, mSubject, mText, mEmailReply); // The local fields you saved earlier
        return null;
    }
.

Altri suggerimenti

Questo non è il modo consigliato di fare:

    @Override
    protected Void doInBackground(final String... strings) {
        try {
            runOnUiThread(new Runnable() {
                public void run() {
                    prepareSending();
                }

            });
        } catch (Exception e) {

        }
        return null;
    }
.

Dovresti usare PublishProgress () per poter eseguire cose sul thread dell'interfaccia utente mentre la tua lavorazione sta succedendo.

Detto questo, non si sta gestendo i casi in cui l'attività può essere distrutta.Ciò potrebbe portare a perdite di memoria e a più asynctasks in esecuzione sullo sfondo.

prova ad arrivare a qualcosa del genere:

public static class MyAsyncTask extends AsyncTask<Void, Void, Void> {

  MyAsyncTask(MyActivity a) {
    activity = new WeakReference<MyActivity>(a);
  }

  @Override
  protected void onPreExecute() {
    if (activity.get()!=null) activity.get().showDialog();
  }

  @Override
  protected Void doInBackground(Void... params) {
    // Upload data from here
  }
  @Override
  protected void onPostExecute(Void params) {    
    if (activity.get()!=null) activity.get().dismissDialog();
  }


  private WeakReference<MyActivity> activity;
}
.

La tua attività è rispostiva per salvare l'attività come stato di non-istanza, chiusura e ricreare la finestra di dialogo quando appropriato, ...

Infine, passa tutte le informazioni necessarie per inviare la posta al costruttore del tuo compito (contenuto, soggetto, ...).Tutti gli accessi interfacciari verranno eseguiti sulla filettatura dell'interfaccia utente quando si crea l'attività (non in downbackground come fai a riguardo).

I problemi bugie qui:

try {
        runOnUiThread(new Runnable() {
                public void run() {
                    prepareSending();
                }

            });
    } catch (Exception e) {

    }
.

1) preparazione ();Il metodo è chiamato sul filo UI.Segnala per capire come usare asynctask In Android

2) Sembra anche che tu abbia l'abitudine di catturare eccezioni generiche e anche non gestirle.Fare riferimento a Guideline di stile .Ti aiuterà molto.

Buona fortuna;)

private class MyAsyncTaskClass extends AsyncTask<String, Integer, Integer> {
        ProgressDialog waitingDialog;

        @Override
        protected void onPreExecute() {
            waitingDialog = new ProgressDialog(MyClass.this);
            waitingDialog.setMessage("Loading ....");
            waitingDialog.setIndeterminate(true);
            waitingDialog.setCancelable(true);
        }

        @Override
        protected Integer doInBackground(final String... strings) {
            setProgress(-1);
            // long process start
            prepareSending();
            // long process end
            setProgress(-2);
            return 0;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {

            if (values[0] == -1) {
                waitingDialog.show();
            } else if (values[2] == -2) {
                waitingDialog.dismiss();
            }
        }

        @Override
        protected Integer onPostExecute(Integer params) {
        }
    }
.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top