Как вернуть 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();