Как вернуть ArrayList из AsyncTask в другой класс?

Я хочу получить список папок Ftp с сервера с помощью AsyncTask и вернуть имена папок ArrayList в основной класс и обновить адаптер Spinner.

В основном классе я получил спиннер с адаптером

//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 в 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?

    }

    }

Итак, как мне заменить Arraylist в AsyncTask на ArrayList в основном классе и динамически обновить программу обновления Spinner?

8 ответов

Решение

Вы уже сделали свой ArrayList статическим, сделайте его публичным. и используйте это по имени вашего класса. и заполните свой ArrayList в onPostExecute(); лайк

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

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

      YourClassName.directoriesTeacher.addAll(result);

     }

- PSEUDO CODE -

Создать кастом interface как следует:

public interface IAsyncTask {

    void IAmFinished(ArrayList<Object> arrayList);

}

Добавить конструктор к вашему AsyncTask:

private IAsyncTask asyncTaskListener;

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

В вашем PostExecute из AsyncTask:

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

В вашем Activity это начинает ваш AsyncTask:

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

Реализуем интерфейс:

public class MyActivity implements IAsyncTask

Реализуйте метод:

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

Я полагаю, вы не хотите, чтобы при извлечении данных был прядильщик, а скорее чтобы заполнить его прядями данными из фоновой задачи? Возврат данных из AsyncTask обычно основан на этом шаблоне с использованием интерфейса.

1) Создайте интерфейс, чтобы вы могли публиковать результаты: (Этот класс вы можете создать в отдельном файле или просто объявить его в любом классе)

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

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) В вашем классе 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) Наконец, чтобы вернуть данные:

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

В вашей AsyncTask вы можете иметь члена (MyActivity m_activity) с тем же классом вашей активности.

В конструкторе AsyncTask установите параметр MyActivity и запишите его в m_activity.

В вашем onPostExecute запустите метод вашей деятельности, который обновит ваш спиннер-адаптер: m_activity.updateSpinner(ftpTeacher );

Методы onPostExecute выполняются в потоке пользовательского интерфейса. Вы можете присвоить результат в postexecute() вашему массиву в методе main. Обновите адаптер, вызвав notifydatasetChanged, чтобы обновить список.

Реализовать listener прохождение ArrayList и использовать этот слушатель для возвращения вашего ArrayList,

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

}

При вызове асинхронной задачи для выполнения операции создайте экземпляр TaskListener следующее:

TaskListener listener = new TaskListener() {

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

Передайте это listenerОбъект в качестве параметра для конструктора асинхронных задач. И создать глобальный экземпляр TaskListener в самой асинхронной задаче. Назначьте TaskListener параметр в конструкторе для глобального экземпляра.

Тогда в onPostExecute класса асинхронных задач:

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

    }

Создайте один интерфейс в вашем классе Asynctask

public interface OnDownload {
        public void onDownloadComplete(ArrayList<String> list);
    }

и в конструкторе этого класса получить этот интерфейс, как показано ниже

private OnDownload mOnDownload;

    public FtpTeacher(OnDownload onDownload) {
        this.mOnDownload = onDownload;
    }

и в onPostExecute отправьте результат через интерфейс, как показано ниже

mOnDownload.onDownloadComplete(listResult);

Теперь реализуйте интерфейс в основном классе, вы получите обновленный список, как показано ниже

public class MainActivity extends Activity implements OnDownload {

  public void sampleCall() {
     new FtpTeacher(this).execute();
  }
      @Override
    public void onDownloadComplete(ArrayList<String> list) {
        //Here you can update the spinner
    }
}

В главном разделе, где вы вызываете AsyncTask, перезапишите метод onPostExecute и поместите туда свой адаптер. Он вызывается в потоке пользовательского интерфейса, поэтому он сохраняется.

Итак, где вы вызываете 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();
Другие вопросы по тегам