使用AsyncTask的应用程序仍然占用UI线程?

时间:2012-12-04 13:33:53

标签: android android-intent asynchronous android-asynctask

我已经编写了一个位于' Share via'菜单(用于快速通过电子邮件发送自己链接到我在网上找到或在RSS阅读器中查找的内容)为此我使用了intent.action.SEND intent-filter:

    <activity
        android:name="uk.co.baroquedub.checkit.MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.SEND" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:mimeType="text/plain" />
           </intent-filter>
    </activity>

这是MainActivity包,它从Intent获取页面标题和网址,并使用单独的GMailSender类直接向我发送此信息:

package uk.co.baroquedub.checkit;

import android.app.Activity;
import android.app.Dialog;
import android.content.Intent;

import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends Activity {

private static Dialog dialog;

String title;
String url;
String message;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    Intent intent = getIntent();
    intent.setFlags( Intent.FLAG_ACTIVITY_CLEAR_TOP );
    String action = intent.getAction();

    // if this is from the share menu
   if (Intent.ACTION_SEND.equals(action)) {   
           title = intent.getStringExtra(Intent.EXTRA_SUBJECT);
           url = intent.getStringExtra(Intent.EXTRA_TEXT);

           // Flipboard fix (remove title in URL)
           url = url.replace(title, "");

           if (url != null){
            url = title+"\n"+url;
           } else {
            url = "error getting URL";
           }

    // Asynch Task
                doSendTask task = new doSendTask();
                task.execute(new String[] { url });   

   }

}

protected void showDialog (String response){
dialog = new Dialog(this);
    dialog.setContentView(R.layout.dialog);
    dialog.setTitle(response);

    Button button = (Button) dialog.findViewById(R.id.Button01);
    button.setOnClickListener(new View.OnClickListener() {  
        @Override  
        public void onClick(View view) {  

            dialog.dismiss();   
            finish();
        }  
    });

    dialog.show();
}

private class doSendTask extends AsyncTask<String, Void, String> {
    @Override
    protected String doInBackground(String... urls) {
      String response = "";

      String senderPassword = getResources().getString(R.string.senderPassword); 
      String senderEmail = getResources().getString(R.string.senderEmail); 
      String recipientEmail = getResources().getString(R.string.recipientEmail); 
      String subjectText = getResources().getString(R.string.subjectText);

      GMailSender sender = new GMailSender(senderEmail, senderPassword);
      try {
        sender.sendMail(subjectText,   
                url,   
                  senderEmail,   
                  recipientEmail);
            response = "Email sent";
        } catch (Exception e) {
            //Log.e("SendMail", e.getMessage(), e); 
            response = "Error sending email";
        }

      return response;
    }

    @Override
        protected void onPostExecute(String result) {
            showDialog(result);
    }
}

@Override
public void onDestroy() {
    super.onDestroy();

    /*
     * Kill application when the root activity is killed.
     */
    UIHelper.killApp(true);
}

}

版本1工作正常,但我发送的电子邮件来自于&#39; onCreate&#39;这意味着直到&#34;电子邮件发送&#34;通知出现后,手机的浏览器将无法响应(我无法滚动或导航到新页面)。然后我更改了代码(如上所述)以将电子邮件发送到AsyncTask类中 - 但是尽管应用程序仍然有效,但在对话框出现之前,浏览器仍然没有响应。 AsyncTask似乎没有任何区别。

任何人都可以解释原因,并希望提出解决方案吗?

4 个答案:

答案 0 :(得分:1)

答案? ...我已经大量简化了上面的代码,试图找出可能出错的地方。我创建了一个沼泽标准App并使用了以下内容:

package uk.co.baroquedub.testcheck;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;

import android.widget.Toast;

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    doSendTask task = new doSendTask();
    task.execute(new String[] { "urlString" });
}

protected void showDialog (String response){
    Toast.makeText(this, response, Toast.LENGTH_SHORT).show();
    finish();
}

private class doSendTask extends AsyncTask<String, Void, String> {
    @Override
    protected String doInBackground(String... urls) {
      String response = "";

      try { 
          Thread.sleep(5000);
          response = "Waited";
      }
      catch (InterruptedException ex) {  }

      return response;
    }

    @Override
        protected void onPostExecute(String result) {
            showDialog(result);
    }
}

}

这让我看到了什么问题:我的应用程序在浏览器顶部打开(出现一个白色屏幕,标题栏显示应用程序的名称)我用我的应用程序没有注意到这一点(因为我使用的是一个使用透明背景的主题。

请参阅:screencast for demo of problem

因此虽然电子邮件是作为AsyncTask发送的,但是当发生这种情况时,应用程序本身就会出现在浏览器之上 - 这就是阻止它被访问的原因。 (我将作为单独的问题发布关于此的帮助请求)

答案 1 :(得分:0)

不,AsyncTask不与您的UI线程绑定,并且您不会像在onCreate()中进行冗长操作时那样阻止它。

答案 2 :(得分:0)

我认为您的代码中存在错误:

 doSendTask task = new doSendTask();
 task.execute(url); // if you want to put more urls  task.execute(url,url1,url2);
 try {
        sender.sendMail(subjectText,   
                url[0],             // get the first url
                  senderEmail,   
                  recipientEmail);
            response = "Email sent";
        } catch (Exception e) {
            //Log.e("SendMail", e.getMessage(), e); 
            response = "Error sending email";
        }

答案 3 :(得分:0)

ASyncTasks确实是在他们自己的线程上执行的,如reference page所示。

当您为此活动创建意图时,您将传递标记'FLAG_ACTIVITY_CLEAR_TOP',其中显示的内容类似于“... ...之上的所有其他活动将被关闭,此意图将被传递给(现在)最重要的是旧的活动作为新的意图。'这是不是意味着旧活动被锁定,直到这个新活动终止?