我应该在扩展Activity的MainActivity中使用AsyncTask类吗?

14

我想知道AsyncTask是否可以在主活动(MainActivity.java)中使用线程。

例如,我注意到许多教程在使用AsyncTask时,在主类中声明一个继承了Activity的私有类,而不是为该AsyncTask (MyAsyncTask.java)创建一个独立的.java文件。

但是我发现当使用一个独立文件时,我无法运行runOnUIThread(),因为它属于Activity类,那么我如何在这个继承了AsyncTask而不是Activity的独立AsyncTask(MyAsyncTask.java)中使用这个方法呢?


为什么你想在 AsyncTask 中调用 runOnUIThread 函数? - EvilDuck
要更改 TextView,它们不能从其他线程中更改。 - Alex
你可以在onPostExecute和onPreExecute中更新UI。 - Stefan de Bruijn
1
我已经编辑了我的回答。你可以按照我写的代码来更新你的TextView。希望能对你有所帮助! - Akbari Dipali
2
使用onPreExecute()、onProgressUpdate()和onPostExecute()来使用Activity方法。onProgressUpdate()用于通知进度。取决于你。最佳AsyncTask教程 - Thomas Daniel
4个回答

15

完全没问题。我经常这样做,但这取决于你如何使用它。如果可能被其他活动(Activities)使用,则会给它一个单独的类或共享类。但如果它只是为了一个特定的目的,那么我会将其作为MainActivity的内部类。

将其作为内部类的好处在于它可以直接访问该类的成员变量。如果您将其作为单独的类,则只需为其创建一个构造函数,以便在需要传递params诸如context或其他变量时使用。

我不知道您具体在做什么,但我不确定您是否需要runOnUiThread()。您可以在您的AsyncTask文件中创建一个构造函数,并将其作为参数接受context和其他所需内容。然后,您可以在onPostExecute()中更新UI

例子

public class MyAsyncTask extends AsyncTask{

    private Context context; 

    public MyAsyncTask(Context context) {  // can take other params if needed
        this.context = context;
    }

    // Add your AsyncTask methods and logic
    //you can use your context variable in onPostExecute() to manipulate activity UI
}

然后在你的MainActivity中调用它。

MyAsyncTask myTask = new MyAsyncTask(this);  //can pass other variables as needed
myTask.execute();

谢谢你的回答,我很喜欢它。问题是如果runOnUIThread()是一个独立的文件,它就不能运行,我必须使用内部类来运行它,但我不想这样做,因为我将在3个活动中使用相同的类,并且我不想在每个活动中放置AsyncTask的整个代码块。 - Alex
你不必使用内部类。在构造函数中传递一个对活动的引用作为参数(就像codeMagic所描述的那样)。然后使用该活动的引用来调用runOnUIThread()方法。 - Sababado
如果需要的话,我添加了一个小例子。好的,很好,我很高兴它对你有用 :) - codeMagic
抱歉!那是我的失误!:D - Alex

9
通常,我们把AsyncTask放在同一个类中,以使它更清晰地被同一活动使用。
如果您希望AsyncTask能够被多个活动重复使用,则可以简单地创建一个独立的类,并通过构造函数从活动中传递参数。
您可以在您的AsyncTask中创建一个接口,用于将AsyncTask的响应发送到您的活动中,如下所示,并在需要时调用您的监听器方法。我已经称之为onPostExecute()
public class DeckDownloader extends AsyncTask<Void, Void, String> {

    OnDownloadUpdateListener listener;
    
    public interface OnDownloadUpdateListener {
         public void OnDownloadDeckFinish(String Response);     
    }


    public DeckDownloader(Context ctx, OnDownloadUpdateListener listener) {
         mContext = ctx;
         this.listener = listener;
    }

    @Override
    protected String doInBackground(Void... params) {
         String str = "downloading";
         //your async code goes here
         return str;
    }

     @Override
     protected void onPreExecute() {
          super.onPreExecute();
     }

     @Override
     protected void onPostExecute(String result) {
          if( listener != null ) {
                listener.OnDownloadDeckProgress(result);
          }
     }
}

而在您的Activity类中,您需要实现该侦听器并编写代码以在该实现方法中更新textview:

    public class myActivity extends Activity{
          private DeckDownloader.OnDownloadUpdateListener downloadListener;
          TextView txtAsyncResponse;

          @Override
          public void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              txtAsyncResponse = (TextView) findViewById(R.id.txtAsyncResponse);
    

            downloadListener = new DeckDownloader.OnDownloadUpdateListener() {
               @Override
               public void OnDownloadDeckFinish(String Response) {
                    txtAsyncResponse.setText(Response);
               }
            };
    }

您可以编写以下代码在您的活动中启动AsyncTask,每当需要时,例如按钮单击事件或其他情况

 DeckDownloader mTask = new DeckDownloader(this.getApplicationContext(), downloadListener);
 mTask.execute();

这可能是您想要的东西!


如何更改视图?如果它是一个独立的类,我就无法运行runOnUIThread()。 - Alex
为什么要使用runOnUIThread?你对它有什么需求? - Akbari Dipali
1
我在问题中看到了你的评论,是不是你需要在完成AsyncTask后更改调用者活动中的TextView内容?我的理解正确吗? - Akbari Dipali
请随意提出任何问题,并让我知道这对您是否有用。 - Akbari Dipali
1
非常感谢你抽出时间来帮助我,我真的很感激。今晚我会尝试这个方法,再次非常感谢你,我会尽快给你回复! - Alex

2
是的。你可以在 MainActivity.java 中创建 AsyncTask类
public class CategoryListScreen extends Activity {


    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        new loadcategory().execute();
    }

    class loadcategory extends AsyncTask<Void, Void, Void> {

        @Override
        protected Void doInBackground(Void... params) { }
        protected void onPostExecute(Void param) { }
    } // AsyncTask over
}//main class over

1
问题在于我不想将它用作内部类,而是想将其用作独立的类。 - Alex

2

我相信大多数教程都会选择易于理解/阅读的内容,而不是最好的内容。

通过使用内部类,你可以保留 Activity 的变量,这可能更简单。

总的来说,你应该尽可能地封装,包括你的 AsyncTasks,这样你就可以从代码的任何其他点重用它们。


是的,这就是为什么我想为它制作一个独立文件,以便我不仅可以将其用于一个目的,还可以用于多种目的。 - Alex

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接