Loader is useful while maintaining life cycle of activity and avoiding performing big task again and again. Loader provide a way to keep old data while changing orientation. Every loader has its own unique ID and its created only once. Next time it will use the previous instance.
Loader is discussed at various place but creating your own custom loader is the topic remains to discuss. Let take one case where loader is useful in android
Suppose application download data from network and show inside a list. suddenly user change phone orientation. Data will start downloading again. To avoid this case, Loader are right thing to use
Loader life cycle include three method
- public Loader<DataHandler> onCreateLoader(int arg0, Bundle arg1) , called when loader initialize once only
- public void onLoadFinished(Loader<DataHandler> arg0, DataHandler arg1) every time when applciation interact with Loader. And return data
Note: Here DataHandler is application custom class
- public void onLoaderReset(Loader<DataHandler> arg0) to change UI and remove previous view
Now this article will include steps and description to create its own custom loader . It had one list fragment. And after download data using AsyncTaskLoader<DataHandler>, we shows data inside List Fragment
1) One fragment activity is base activity that include on list fragment inside main frame layout
2) Now create List Fragment and initialize the Loader with Loader manager like
getActivity().getSupportLoaderManager().initLoader(10, null, this).
Loader manager has three argument Loader _ID, Bundle data and LoaderManager.LoaderCallbacks<DataHandler>. Now it will force you to override required method of Loader Manager callback
First will be create loader, here we start one Asynchronous Loader to load data.
@Override
public Loader<DataHandler> onCreateLoader(int arg0, Bundle arg1) {
AsynChro asynChro = new AsynChro(ListFragmentExp.this.getActivity());
asynChro.forceLoad();
return asynChro;
}
Loader reset call everytime it interact with loader
@Override
public void onLoaderReset(Loader<DataHandler> arg0) {
mlisListView.setAdapter(null);
}
Loader loaded then it call this method , return with data everytime once it downloaded
@Override
public void onLoadFinished(Loader<DataHandler> arg0, DataHandler arg1) {
mlisListView.setAdapter(new DataBinder(getActivity(), arg1.getData()));
setListShown(true);
}
3) Once we downloaded data, we just have traditional way to set it inside List Fragment using BaseAdapter
These above images show how loader maintain life cycle of data when you change your orientation .
LoaderManager can return any kind of data.
Here i have my custom class DataHolder and i am returning data as DataHolder
So Lets go step by step with loader in coding
Activity Class for initiation
package com.loader;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.widget.FrameLayout;
public class MainActivity extends FragmentActivity{
FragmentTransaction mTFragmentTransaction;
FragmentManager mManFragmentManager;
ListFragmentExp mListFragment;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mListFragment = new ListFragmentExp();
FrameLayout cursor = (FrameLayout) findViewById(R.id.listFragment);
mManFragmentManager = getSupportFragmentManager();
if (mManFragmentManager.findFragmentByTag("Tag") == null) {
mTFragmentTransaction = mManFragmentManager.beginTransaction();
mTFragmentTransaction.add(cursor.getId(), mListFragment, "Tag");
mTFragmentTransaction.commit();
}
}
}
A List Fragment loading data using LoaderManager and displaying
package com.loader;
import java.util.ArrayList;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.ListFragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.AsyncTaskLoader;
import android.support.v4.content.Loader;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
public class ListFragmentExp extends ListFragment implements
LoaderManager.LoaderCallbacks<DataHandler> {
// This is the Adapter being used to display the list's data.
BaseAdapter mAdapter;
public static ListView mlisListView;
// If non-null, this is the current filter the user has provided.
String mCurFilter;
public static FragmentActivity mAcFragmentActivity;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mAcFragmentActivity = getActivity();
// Give some text to display if there is no data. In a real
// application this would come from a resource.
setEmptyText("No phone numbers");
// Create an empty adapter we will use to display the loaded data.
setListAdapter(mAdapter);
// Start out with a progress indicator.
setListShown(false);
mlisListView = getListView();
getActivity().getSupportLoaderManager().initLoader(10, null, this);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return super.onCreateView(inflater, container, savedInstanceState);
}
@Override
public Loader<DataHandler> onCreateLoader(int arg0, Bundle arg1) {
AsynChro asynChro = new AsynChro(ListFragmentExp.this.getActivity());
asynChro.forceLoad();
return asynChro;
}
@Override
public void onLoadFinished(Loader<DataHandler> arg0, DataHandler arg1) {
mlisListView.setAdapter(new DataBinder(getActivity(), arg1.getData()));
setListShown(true);
}
@Override
public void onLoaderReset(Loader<DataHandler> arg0) {
mlisListView.setAdapter(null);
}
public static class AsynChro extends AsyncTaskLoader<DataHandler> {
DataHandler mHaDataHandler;
public AsynChro(Context context) {
super(context);
mHaDataHandler = new DataHandler();
}
@Override
public DataHandler loadInBackground() {
ArrayList<String> temp = new ArrayList<String>();
for (int i = 0; i < 100; i++) {
temp.add("Counting-----" + i);
}
try {
synchronized (this) {
wait(5000);
}
} catch (Exception e) {
e.getMessage();
}
mHaDataHandler.setData(temp);
return mHaDataHandler;
}
@Override
public void deliverResult(DataHandler data) {
super.deliverResult(data);
mlisListView.setAdapter(new DataBinder(mAcFragmentActivity, data
.getData()));
}
}
}
And finally one object to save data. I make DataHandler class to save data
package com.loader;
import java.util.ArrayList;
public class DataHandler {
ArrayList<String> mListStrings = new ArrayList<String>();
public void setData(ArrayList<String> temp) {
mListStrings = temp;
}
public ArrayList<String> getData() {
return mListStrings;
}
}
Now Binding all data inside a List Fragment using BaseAdapter
package com.loader;
import java.util.ArrayList;
import android.graphics.Color;
import android.support.v4.app.FragmentActivity;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
public class DataBinder extends BaseAdapter {
ArrayList<String> mLisArrayList;
FragmentActivity mAtcFragmentActivity;
public DataBinder(FragmentActivity mActivity, ArrayList<String> mList) {
mLisArrayList = mList;
mAtcFragmentActivity = mActivity;
}
@Override
public int getCount() {
return mLisArrayList.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView mTextView;
if (convertView == null) {
mTextView = new TextView(mAtcFragmentActivity);
mTextView.setLayoutParams(new ListView.LayoutParams(
LayoutParams.FILL_PARENT, 60));
mTextView.setGravity(Gravity.CENTER_HORIZONTAL
| Gravity.CENTER_VERTICAL);
mTextView.setTextSize(20);
mTextView.setBackgroundColor(Color.GRAY);
mTextView.setTextColor(Color.GREEN);
convertView = mTextView;
} else {
mTextView = (TextView) convertView;
}
mTextView.setText(mLisArrayList.get(position));
return convertView;
}
}
Feel free to download code