I am trying to implement a ListFragment with AsynchTaskLoader that contains datasource but I have trouble in refreshing listFragment as it doesnt get refresh when I change data from background in my BaseAsyncTaskLoader
The code is attached:
The Activity that loads listfragment
public class BaseFragmentManager extends FragmentActivity implements ListItemSelectedListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_stack);
Button btnLoadMore = (Button) findViewById(R.id.new_fragment);
btnLoadMore.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent();
i.setAction("com.test.gcc.myintent.loader.BaseAsyncTaskLoader");
i.putExtra("action", "loadmore");
sendBroadcast(i);
}
});
BaseListFragmentActivity fragment = new BaseListFragmentActivity();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment_container, fragment);
transaction.addToBackStack(null);
transaction.commit();
}
@Override
public void onListItemSelected(int index) {
Log.i("Error", "itemSelected-"+index);
}
}
My LISTFragment class that is not being refreshed
public class BaseListFragmentActivity extends ListFragment implements LoaderManager.LoaderCallbacks<ArrayList<MyData>> {
private ListItemSelectedListener selectedListener;
private int index = 0;
private ArrayList<MyData> data;
private BaseAsyncTaskLoader astask;
private CustomListAdapter adapter;
@Override public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
this.data = MyDataBroker.getDefaultBroker().getData();
this.adapter = new CustomListAdapter(this.getActivity(), data);
setListAdapter(this.adapter);
setListShown(false);
getLoaderManager().initLoader(0, null, this);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
}
@Override public Loader<ArrayList<MyData>> onCreateLoader(int id, Bundle args) {
// This is called when a new Loader needs to be created. This
// sample only has one Loader with no arguments, so it is simple.
astask = new BaseAsyncTaskLoader(this.getActivity());//new AppListLoader(getActivity());
return astask;
}
@Override
public void onLoadFinished(Loader<ArrayList<MyData>> Loader, ArrayList<MyData> data) {
this.adapter.setData(data);
if (isResumed()) {
setListShown(true);
} else {
setListShownNoAnimation(true);
}
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
index = position;
selectedListener.onListItemSelected(position);
}
@Override
public void onLoaderReset(Loader<ArrayList<MyData>> data) {
adapter.setData(null);
}
public interface ListItemSelectedListener {
public void onListItemSelected(int index);
}
}
AsynchTaskLoader Class
public class BaseAsyncTaskLoader extends AsyncTaskLoader<ArrayList<MyData>> {
private ArrayList<MyData> data;
private int pageNumber;
private boolean listenerIsRegistered = false;
private com.test.gcc.myintent.test.BaseAsyncTaskLoader.CustomBroadCastListener listener;
public BaseAsyncTaskLoader(Context context) {
super(context);
pageNumber = 1;
listener = new CustomBroadCastListener();
if (!listenerIsRegistered) {
context.registerReceiver(listener, new IntentFilter("com.test.gcc.myintent.loader.BaseAsyncTaskLoader"));
listenerIsRegistered = true;
}
}
/**
* This is where the bulk of our work is done. This function is called in a
* background thread and should generate a new set of data to be published
* by the loader.
*/
@Override
public ArrayList<MyData> loadInBackground() {
final Context context = getContext();
return this.loadInBackgroud();
}
private ArrayList<MyData> loadInBackgroud() {
return MyDataBroker.getDefaultBroker().getData(); //returns some data of custom type.
}
/**
* Called when there is new data to deliver to the client. The super class
* will take care of delivering it; the implementation here just adds a
* little more logic.
*/
@Override
public void deliverResult(ArrayList<MyData> data) {
if (isReset()) {
if (data != null) {
onReleaseResources(data);
}
}
if (isStarted()) {
super.deliverResult(data);
}
}
/**
* Handles a request to start the Loader.
*/
@Override
protected void onStartLoading() {
if (this.data != null) {
deliverResult(this.data);
}
if (takeContentChanged() || this.data == null) {
forceLoad();
}
}
/**
* Handles a request to stop the Loader.
*/
@Override
protected void onStopLoading() {
// Attempt to cancel the current load task if possible.
cancelLoad();
}
/**
* Handles a request to cancel a load.
*/
@Override
public void onCanceled(ArrayList<MyData> data) {
super.onCanceled(data);
onReleaseResources(data);
}
/**
* Handles a request to completely reset the Loader.
*/
@Override
protected void onReset() {
super.onReset();
onStopLoading();
this.data = null;
}
public void onLoadMore(){
this.loadInBackground();
}
protected class CustomBroadCastListener extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals("com.test.gcc.myintent.loader.BaseAsyncTaskLoader")) {
if(intent.getStringExtra("action") != null &&
intent.getStringExtra("action").equals("loadmore")){
loadInBackground();
}
}
}
}
/**
* Helper function to take care of releasing resources associated with an
* actively loaded data set.
*/
protected void onReleaseResources(List<MyData> apps) {
//NOTUSED
}
}
From debug I can see that the data is being loaded but the listFragment doesn’t refresh and as far I know we don’t have to refresh listFragment manually as it is attached to data source it should be refreshed automatically.
Just call restart loader instead in loadMOre and better call it from ListFragment
and changing the onFinished to as mentioned by @doorstuck
A better example can be found at here