0

我有一门课可以发送各种带有附件的邮件。

因为该方法sendEmail(addresses);需要时间来上传附件和发送电子邮件,所以我创建了一个 AsyncTask 来显示一个等待对话框,

然而,不幸的是,在发送过程中,应用程序会冻结,直到它终止发送而不显示任何内容(或者有时在程序结束前显示一个冻结的等待窗口片刻)

我的类中的相关代码部分如下

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
    ......

}
4

4 回答 4

2

问题

我敢打赌这是因为您在 UI 线程上运行所有内容:

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

            });
        } catch (Exception e) {

        }
        return null;
    }

改为这样做!

运行doInBackground基于非 UI 依赖的所有代码。

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

访问用户界面

如果您需要从 UI 或 UI 线程上的任何其他内容访问数据,请先执行此操作。

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

然后将它们发送到您的方法

输入prepareSendingsendEmail接受该数据作为参数:

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) {
    // ...
}

最后,您需要从以下位置发送doInBackground

    @Override
    protected Void doInBackground(final String... strings) {
        prepareSending(mName, mSubject, mText, mEmailReply); // The local fields you saved earlier
        return null;
    }
于 2012-10-03T20:31:54.267 回答
0

这不是推荐的做法:

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

            });
        } catch (Exception e) {

        }
        return null;
    }

您应该使用 publishProgress() 以便在处理过程中在 UI 线程上运行内容。

也就是说,您也没有管理可以破坏活动的情况。这可能会导致内存泄漏和多个 AsyncTask 在后台运行。

尝试得到类似的东西:

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

您的活动可以响应将任务保存为非实例状态,在适当时关闭并重新创建对话框,...

最后,将发送邮件所需的所有信息传递给您的任务构造函数(内容、主题、...)。然后,当您创建任务时,所有 UI 访问都将在 UI 线程上完成(而不是像您目前所做的那样在 doInBackground 中)。

于 2012-10-03T20:32:04.673 回答
0

问题出在这里:

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

            });
    } catch (Exception e) {

    }

1)准备发送();在 UI 线程上调用方法。参考这里了解如何在Android中使用AsyncTask

2) 此外,您似乎习惯于捕捉通用异常并且也不处理它​​们。请参阅代码样式指南。这会对你有很大帮助。

祝你好运 ;)

于 2012-10-03T20:40:51.990 回答
0
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) {
        }
    }
于 2012-10-03T20:59:16.553 回答