ASyncTask только при первом открытии

У меня есть активность, которая расширяет FragmentActivity

В первом фрагменте (HomePage, который расширяет фрагмент) мне нужно загрузить данные из Интернета, поэтому я использую ASyncTask.
Теперь проблема: мне не нужно проверять и загружать данные каждый раз, когда фрагмент создается/прикрепляется
но только в первом случае я хочу сохранить состояние и снова загрузить данные только для следующего действия onCreate (надеюсь, это означает следующее открытие приложения, но мы знаем, что это не так)

Итак... Куда мне поместить мой ASyntTask.execute()? OnCreate внутри фрагмента? OnCreateView внутри фрагмента? При прикреплении внутри фрагмента? или OnCreate of Activity, сохранять данные в Bundle и затем передавать их моему фрагменту?

Или, может быть, другие решения для этого?

ИЗМЕНИТЬ

Решено!

Итак, в моем OnCreate [Fragment] я добавил

 if(savedInstanceState != null) {

        data = (data[]) savedInstanceState.getParcelableArray("key");
    }
    else
        new LoadMostBooks().execute();

Но я не установил InstanceRetain(True), потому что мне нужно всегда проходить через onCreate();

Затем в методе onCreateView() я добавил также проверку

if(savedInstanceState != null) {
        myCustomArrayAdapter = new CustomArrayArrayAdapter(mContext,data);
        myListView.setAdapter(myCustomArrayAdapter);
    }

Мне также нужно было убедиться в сохранении экземпляра с

 @Override
public void onSaveInstanceState( Bundle outState ) {
    super.onSaveInstanceState( outState );
    outState.putParcelableArray("key",data);
}

В конце концов мне пришлось сделать данные (пользовательский объект) реализованными Parcelable, чтобы убедиться, что все работает!


person Tizianoreica    schedule 24.07.2013    source источник
comment
В каком сценарии ваш фрагмент будет запускать этот асинхронный код, когда вы этого не хотите, и где в данный момент находится асинхронная задача?   -  person IAmGroot    schedule 24.07.2013
comment
Я открываю свое приложение, и мне нужно проверить и загрузить данные из Интернета (но эта команда находится внутри домашнего фрагмента, я имею в виду, что первый фрагмент показывается пользователю). Мой код ASync находится внутри моего класса Fragment.   -  person Tizianoreica    schedule 25.07.2013


Ответы (4)


Вы можете просто сохранить свои данные вSaveInstanceState, а затем проверить onCreate, есть ли они там или нет.

private Data[] mData;

@Override
public void onCreate( Bundle savedInstanceState ) {

    super.onCreate( savedInstanceState );
    setRetainInstance( true );
    if ( savedInstanceState != null && savedInstanceState.containsKey( "key" ) ) {

        mData = (Data[]) savedInstanceState.getParcelableArray( "key" );
    }
    else {
        new myAsync() {

            @Override
            public void onPostExecute( Data[] data ) {

                mData = data;
            }
        }.execute();
    }
}

@Override
public void onSaveInstanceState( Bundle outState ) {

    super.onSaveInstanceState( outState );
    if ( mData != null ) {

        outState.putParcelableArray( "key", mData );
    }
}
person James McCracken    schedule 24.07.2013
comment
Но при создании фрагмента или активности? - person Tizianoreica; 25.07.2013
comment
Еще раз извините, но setRetainInstance(true) заставляет onCreate вызываться только один раз, не так ли? Итак, почему я должен проверять наличие saveInstanceState в методе onCreate()? Разве я не должен проверять это на onAttach или onStart? - person Tizianoreica; 25.07.2013

Единственное, что вам нужно сделать, это: проверить, загружаются ли ваши данные или нет, если загружены, то не нужно перезагружать, если не загружать данные, то.

сделайте свой фрагмент как singleInstance, предоставив частный конструктор:

  public static YourFragment mInstance;
         private YourFrament(){//empty constructor
          super();
         }
         public static YourFragment getInstance(){
          if(mInstance==null){
           mInstance = new YourFrament();
         }
          return mInstance;
         }

заявить о своем держателе данных

private List<DataType> mDatas;

предположим, что вы вызываете свой AsyncTask в onActivityCreated : сначала проверьте свои данные:

if(mDatas==null||mData.size<=0){
//here you need to get data by call your AsyncTask
yourAsyncTask = new AsyncTask...
yourAsyncTask.execute()
}else{
//here you have the data already, no need to load
}

и в методе onPostExecute() вашего AsyncTask:

 mDatas = new ArrayList<DataType>();
 mDatas=....// init your data value
person Linh Nguyen    schedule 25.07.2013

Вы можете заставить класс активности предоставлять данные (лениво):

private Object data;

public static interface Callback{
    public void onData(Object data);
}

public void getData(final Callback c){

  if(data != null){
    c.onData(data);
  }else {

      AsyncTask<Void,Void,Object> task = new AsyncTask<Void, Void, Object>() {
          @Override
          protected Object doInBackground(Void... pVoids) {
              //--load data--
              return new Object();
          }

          @Override
          protected void onPostExecute(Object result) {
              super.onPostExecute(result);
              data = result;
              c.onData(data);
          }
      }.execute();

  }

}

И запросите данные в классе фрагментов:

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    if(getActivity() instanceof MyActivity){
        ((MyActivity) getActivity()).getData(new MyActivity.Callback() {
            @Override
            public void onData(Object data) {
                //--do something with the data in fragment
            }
        });
    }
}
person S.D.    schedule 25.07.2013

Что вы можете сделать, так это создать статическое поле в своем первом действии.

общедоступный статический счетчик целых чисел = 0;

и в вашем фрагменте onCreate вы делаете:

if (counter == 0){
//execute Async

counter++;
}

и он никогда не будет выполнен снова (счетчик никогда не будет снова равен 0), пока вы не уничтожите свою активность.

person Victor Laerte    schedule 24.07.2013
comment
Это не решает проблему сохранения и перезагрузки данных позже. - person Rarw; 24.07.2013