Tizianoreica
Tizianoreica

Reputation: 2236

ASyncTask only on First open

I have an Activity that extends FragmentActivity

In first Fragment (HomePage that extends Fragment) I need to load data from web, so I use ASyncTask.
Now the problem: I don't need to check and load data everytime Fragment is created/attach
but just in first instance, then I want to save state and load again data only on next onCreate Activity (That I hope it means next open of app, but we know that it doesn't)

So.. Where Should I put my ASyntTask.execute()? OnCreate inside Fragment? OnCreateView inside Fragment? On Attach inside Fragment? or OnCreate of Activity, store data in Bundle and then pass them to my Fragment?

Or, maybe other solutions to this?

EDIT

Resolved!

So on my OnCreate [Fragment] I added a

 if(savedInstanceState != null) {

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

But I didn't setInstanceRetain(True) cause I need to pass always through onCreate();

Then on onCreateView() Method I added also a check

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

I also needed to make sure about save instance with a

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

At the end I had to make data (Custom Object) implemented Parcelable to make sure everythign works!

Upvotes: 0

Views: 1250

Answers (4)

Victor Laerte
Victor Laerte

Reputation: 6556

What you can do is create a static field in your first activity.

public static int counter = 0;

and in your onCreate fragment you do:

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

counter++;
}

and it will never executed again (counter will never be 0 again) until you destroy your activity.

Upvotes: 0

s.d
s.d

Reputation: 29436

You can make activity class provide data (lazily):

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();

  }

}

And ask for data in fragment class:

@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
            }
        });
    }
}

Upvotes: 0

Linh Nguyen
Linh Nguyen

Reputation: 1264

only thing you need to do is : check whenever you data is loaded or not, if loaded then no need to reload ,if not load data then.

make your Fragment as singleInstance by provide private constructor :

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

declare your data holder

private List<DataType> mDatas;

assume that you call your AsyncTask in your onActivityCreated : check your data first:

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
}

and on your AsyncTask's onPostExecute() method :

 mDatas = new ArrayList<DataType>();
 mDatas=....// init your data value

Upvotes: 0

James McCracken
James McCracken

Reputation: 15766

You can just retain your data onSaveInstanceState then check in onCreate if its there or not.

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 );
    }
}

Upvotes: 2

Related Questions