简体   繁体   English

如何将 ArrayList 从 AsyncTask 返回到另一个类?

[英]How to return ArrayList from AsyncTask to another class?

i want to get Ftp folders list from server using AsyncTask and return folders names ArrayList to main class and update spinner adapter.我想使用 AsyncTask 从服务器获取 Ftp 文件夹列表,并将文件夹名称 ArrayList 返回到主类并更新微调适配器。

In main class i got spinner with adapter在主课上,我得到了带适配器的微调器

//the array i want to update in AsyncTask
static ArrayList<String> directoriesTeacher = new ArrayList<String>();

//The adapter
createfile_spinTeacher = (Spinner) findViewById(R.id.createfile_spinTeacher);   
final ArrayAdapter<String> dataAdapterTeacher = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item,directoriesTeacher);
dataAdapterTeacher.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
createfile_spinTeacher.setAdapter(dataAdapterTeacher);

An in AsyncTask: AsyncTask 中的一个:

    package com.nedoGarazas.learnanylanguage;

    import java.util.ArrayList;

    import org.apache.commons.net.ftp.FTP;
    import org.apache.commons.net.ftp.FTPClient;
    import org.apache.commons.net.ftp.FTPFile;
    import org.apache.commons.net.ftp.FTPReply;

    import android.os.AsyncTask;
    import android.util.Log;

    public class FtpTeacher extends AsyncTask<ArrayList<String>, Void, ArrayList<String>> {
    private static final String TAG = "MyFTPClient";
    public FTPClient mFTPClient = null; 
     ArrayList<String> ftpTeacher = new ArrayList<String>();
    @Override
    protected ArrayList<String> doInBackground(ArrayList<String>... params) {
        {                       
            try {
                mFTPClient = new FTPClient();
         // connecting to the host
                mFTPClient.connect("host.ftp.com", 21);

          // now check the reply code, if positive mean connection success
                if     (FTPReply.isPositiveCompletion(mFTPClient.getReplyCode())) {
      // login using username & password
                    boolean status = mFTPClient.login("admin", "admin");
                    if(status == true){

                            try {
                                FTPFile[] ftpFiles = mFTPClient.listFiles("/Wordsftp/");
                                int length = ftpFiles.length;

                                for (int i = 0; i < length; i++) {
                                    String name = ftpFiles[i].getName();
                                    boolean isDirectory = ftpFiles[i].isDirectory();

                                    if (isDirectory) {
//adding to arraylist
                                        ftpTeacher.add(name);
                                        Log.i(TAG, "Yra : " + name);
                                    }
                                    else {
                                        Log.i(TAG, "Directory : " + name);

                                }
                             }
                            } catch(Exception e) {
                            e.printStackTrace();
                        }


                    mFTPClient.setFileType(FTP.ASCII_FILE_TYPE);
                    mFTPClient.enterLocalPassiveMode();


}
                }
} catch(Exception e) {
Log.d(TAG, "Error: could not connect to host ");
}
return ftpTeacher;
} 
            }

    protected ArrayList<String>[] onPostExecute(ArrayList<String>... result) {
        ////How to return?

    }

    }

So how should i replace arraylist in AsyncTask with ArrayList in main class and update spinner updater dinamicly?那么我应该如何用主类中的 ArrayList 替换 AsyncTask 中的 arraylist 并动态更新微调器更新程序?

-- PSEUDO CODE -- -- 伪代码 --

Create a custom interface as followed:创建自定义interface如下:

public interface IAsyncTask {

    void IAmFinished(ArrayList<Object> arrayList);

}

Add a constructor to your AsyncTask :向您的AsyncTask添加一个构造函数:

private IAsyncTask asyncTaskListener;

public MyAsyncTask(IAsyncTask asyncTaskListener){
     this.asyncTaskListener = asyncTaskListener;
}

In your PostExecute of the AsyncTask :AsyncTaskPostExecute中:

public void onPostExecute(List<String> list) {
    asyncTaskListener.IAmFinished(list);
}

In your Activity that starts your AsyncTask :在启动AsyncTask Activity中:

MyAsyncTask asyncTask = new MyAsyncTask(this);
asyncTask.execute(..);

Implement the interface:实现接口:

public class MyActivity implements IAsyncTask

Implement the method:实现方法:

public void IAmFinished(ArrayList<Object> list){
    // Do whatever you want with your returned object
}

You already made your ArrayList static , make it public as well.您已经将 ArrayList 设为static ,也将其设为公开。 and use that by your class name.并通过您的班级名称使用它。 and populate your ArrayList in onPostExecute();并在 onPostExecute() 中填充您的 ArrayList; like喜欢

     protected void onPostExecute(ArrayList<String>... result) {

    if(YourClassName.directoriesTeacher.size()>0)
     {
       YourClassName.directoriesTeacher.clear();
      }

      YourClassName.directoriesTeacher.addAll(result);

     }

I assume you don't want a spinner while fetching data, but rather to fill your spinner with data from the background task?我假设您在获取数据时不想要微调器,而是用后台任务中的数据填充微调器? Returning data from AsyncTask commonly relies on this pattern, using interface.从 AsyncTask 返回数据通常依赖于这种模式,使用接口。

1) Create an interface so that you can post back your results: (This class you can either create in separate file or just declare it in either class) 1)创建一个接口,以便您可以回发您的结果:(您可以在单独的文件中创建该类,也可以在任一类中声明它)

public interface ReturnData{
    void handleReturnData(ArrayList<String> list);
}

2) Implement the ReturnData interface in your main class: 2) 在你的主类中实现 ReturnData 接口:

public class MyMainClass extends Activity implements ReturnData{

    AsyncTask ftpTeacher = new FtpTeacher();//declare your async task

    @Override
    public void onCreate(Bundle savedInstanceState) {
        ftpTeacher.returnData = this; //set this class as receiver for return data
        //set up adapters etc, just like you do now
        ...
    }



     //Your new data will be returned here - update your current adapter with new list
     @Override
     void handleReturnData(ArrayList<String> list){
          directoriesTeacher = list; //assign new data
          dataAdapterTeacher.notifyDataSetChanged();  //Tell adapter it has new data = forces redraw
     }

     ....
}

3) In your AsyncTask class: 3) 在你的 AsyncTask 类中:

public class FtpTeacher extends AsyncTask<ArrayList<String>, Void, ArrayList<String>> {
    private static final String TAG = "MyFTPClient";
    public FTPClient mFTPClient = null; 
    ArrayList<String> ftpTeacher = new ArrayList<String>();
    public ReturnData returnData; // <--- PUBLIC
    ...
 }

4) Finally, to return data: 4)最后,返回数据:

protected ArrayList<String>[] onPostExecute(ArrayList<String>... result) {
    returnData.handleReturnData(result);
}

In your main, where you are calling your AsyncTask, overwrite the onPostExecute method and put your adapter stuff in there.在您调用 AsyncTask 的 main 中,覆盖 onPostExecute 方法并将您的适配器内容放在那里。 It gets called on the UI Thread, so it's save.它在 UI 线程上被调用,所以它被保存。

So where you are calling the AsyncTask, do所以在你调用 AsyncTask 的地方,做

new FTPTeacher() {

 public void onPostExecute(List<String> list) {

     createfile_spinTeacher = (Spinner) findViewById(R.id.createfile_spinTeacher);   
     final ArrayAdapter<String> dataAdapterTeacher = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item,list);
     dataAdapterTeacher.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
     createfile_spinTeacher.setAdapter(dataAdapterTeacher);

 }

}.execute();

onPostExecute methods runs in UI thread. onPostExecute 方法在 UI 线程中运行。 You can assign the result in postexecute() to your arraylist in main method.您可以将 postexecute() 中的结果分配给 main 方法中的数组列表。 Update the adapter by calling notifydatasetChanged to update your listview.通过调用 notifydatasetChanged 更新您的列表视图来更新适配器。

Implement a listener passing ArrayList and use this listener for returning your ArrayList .实现传递ArrayListlistener并使用此侦听器返回您的ArrayList

public interface TaskListener {
    public void onSuccess(ArrayList<String> result);

}

While invoking your async task for operation execution create an instance of TaskListener as follows:在调用异步任务进行操作执行时,创建一个TaskListener实例,如下所示:

TaskListener listener = new TaskListener() {

        @Override
        public void onSuccess(ArrayList<String> result) {
               // Your result will come here
        }
    };

Pass this listener object as a parameter to the async task constructor.将此listener对象作为参数传递给异步任务构造函数。 And create a global instance of TaskListener in the async task itself.并在异步任务本身中创建TaskListener的全局实例。 Assign the TaskListener parameter in the constructor to the global instance.将构造函数中的TaskListener参数分配给全局实例。

Then in the onPostExecute of the async task class:然后在异步任务类的onPostExecute中:

protected ArrayList<String>[] onPostExecute(ArrayList<String>... result) {
        this.taskListenerGlobalInstance(result); // this will invoke the call back method 

    }

In your AsyncTask you could have a member (MyActivity m_activity) with the same class of your activity.在您的 AsyncTask 中,您可以拥有一个与您的活动类相同的成员 (MyActivity m_activity)。

In your AsyncTask constructor, set a MyActivity parameter and record it in m_activity.在您的 AsyncTask 构造函数中,设置一个 MyActivity 参数并将其记录在 m_activity 中。

In your onPostExecute run a method of your activity that refresh your spinner adapter: m_activity.updateSpinner(ftpTeacher );在您的 onPostExecute 中运行刷新微调适配器的活动方法: m_activity.updateSpinner(ftpTeacher );

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM