【问题标题】:App using AsyncTask still hogging the UI thread?使用 AsyncTask 的应用程序仍然占用 UI 线程?
【发布时间】:2012-12-04 13:33:53
【问题描述】:

我编写了一个位于“共享方式”菜单中的应用程序(用于快速通过电子邮件向自己发送指向我在网络上找到的内容或在 RSS 阅读器中查看的内容的链接)为此,我使用了一个 intent.action.SEND意图过滤器:

    <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 中获取页面标题和 url,并使用单独的 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 运行良好,但我从“onCreate”中发送电子邮件,这意味着在“已发送电子邮件”通知出现之前,手机的浏览器将无响应(我无法滚动或导航到新页面)。然后我更改了代码(如上所述)以将电子邮件发送代码放在 AsyncTask 类中 - 但是尽管应用程序仍然可以工作,但浏览器仍然没有响应,直到出现对话框。 AsyncTask 似乎没有任何区别。

谁能解释原因,并希望提出解决方案?

【问题讨论】:

    标签: android android-intent asynchronous android-asynctask


    【解决方案1】:

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

    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 发送的,但在这种情况下,应用程序本身会出现在浏览器的顶部 - 这就是阻止它被访问的原因。 (我将在此问题上发布寻求帮助的请求)

    【讨论】:

    • 这是相关的后续问题:stackoverflow.com/questions/13728628/…
    • 我所做的假设有点道理:您正在创建一个 Activity,它实际上是一个新屏幕。我本来希望它有一个白色的背景,这会让它很明显。
    • 我打算建议使用服务来运行代码(我之前想过,但我不确定你是否需要显示一个弹出窗口,所以我忽略了它),并且有人在您打开的相关问题上这样做了。
    • 另外,我不是 Intents 方面最大的专家,但你为什么要检查 Intent 是否真的是 SEND? Intent 过滤器不是已经解决了这个问题吗?
    【解决方案2】:

    不,AsyncTask 不会绑定到您的 UI 线程,并且您不会像在 onCreate() 中执行一些冗长操作时那样阻塞它。

    【讨论】:

    • 好的,是的 - 你说的是我期望发生的事情,但不幸的是,在发送电子邮件时浏览器确实停止滚动 - 即使作为 AsyncTask 也是如此。你能想到为什么会发生这种情况吗?
    【解决方案3】:

    我认为你的代码有错误:

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

    【讨论】:

    • 谢谢,但不清楚您的建议是什么。您的意思是我应该将变量“url”重新转换为数组而不是字符串,以便我可以传递多个 URL?实际上,该字符串对我来说工作得很好,应用程序也工作得很好——除了在发送电子邮件时阻止网络浏览器滚动。
    【解决方案4】:

    ASyncTask 确实是在它们自己的线程上执行的,正如他们在reference page 上所写的那样。

    当您为此活动创建意图时,您传递了标志“FLAG_ACTIVITY_CLEAR_TOP”,其内容类似于“......在它之上的所有其他活动都将被关闭,并且此意图将被传递到(现在在顶部)旧活动作为新意图。这是否意味着旧的活动被锁定,直到新的活动终止?

    【讨论】:

    • 感谢您的好建议。我不太记得为什么我把那个标志放进去(可能只是从某个地方复制了一个代码 sn-p)。我尝试注释掉该行,但不幸的是,同样的问题仍然存在 - 发送电子邮件时浏览器冻结:/
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    • 2015-05-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多