Issue
I am reading about how to interact between UI and background thread here.
This article has following note:
The AsyncTask does not handle configuration changes automatically, i.e. if the activity is recreated. The programmer has to handle that in his coding. A common solution to this is to declare the AsyncTask in a retained headless fragment.
I dont understand what is retained headless fragment.
For example, in this way I can add fragment:
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
transaction.add(R.id.frame, new MyFragment());
transaction.commit();
And in fragment I can execute AsyncTask like this:
MyTask myTask = new MyTask();
String[] args = {"Hello"};
myTask.execute(args);
Is this called "to declare the AsyncTask in a retained headless fragment"?
Solution
Headless fragment is nothing but a fragment which does not have a view. In onCreate()
of the fragment lifeCycle, use setRetainInstance(true);
. This will not destroy the fragment even if the activity recreates. So if an AsyncTask is running in fragment, on recreation of the activity, you wont lose the AsyncTask.
In onCreate
of the activity, you have to add the fragment with a tag. Before adding, check if the fragment exist using getFragmentManager().findFragmentByTag(TAG)
, if the fragment is null then create a new instance of the fragment and add it.
In Fragment there will not be any view inflated, so no need to override onCreateView()
.
An example of headlessFragment :
public class HeadlessProgressFragment extends Fragment {
private ProgressListener mProgressListener;
private AsyncTask<Void, Integer, Void> mProgressTask;
public interface ProgressListener {
void updateProgress(int progress);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
public void setProgressListener(Context context) {
mProgressListener = (ProgressListener) context;
}
public void startProgress(final int size) {
if (mProgressTask == null || mProgressTask.getStatus() != AsyncTask.Status.RUNNING || mProgressTask.getStatus() == AsyncTask.Status.FINISHED) {
mProgressTask = new AsyncTask<Void, Integer, Void>() {
@Override
protected Void doInBackground(Void... params) {
for (int index = 0; index < size; index++) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
publishProgress(index + 1);
}
}
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
if (mProgressListener != null) {
mProgressListener.updateProgress(values[0]);
}
}
};
mProgressTask.execute();
}
}
}
In Activity Something like this :
public class MainActivity extends FragmentActivity implements HeadlessProgressFragment.ProgressListener {
private static final String TAG = "progress_fragment";
private ProgressBar mProgressBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.dummy_view);
mHeadlessProgressFragment = (HeadlessProgressFragment) getSupportFragmentManager().findFragmentByTag(TAG);
if (mHeadlessProgressFragment == null) {
mHeadlessProgressFragment = new HeadlessProgressFragment();
getSupportFragmentManager().beginTransaction().add(mHeadlessProgressFragment,TAG).commit();
}
mHeadlessProgressFragment.setProgressListener(this);
mProgressBar = (ProgressBar) findViewById(R.id.progress_bar);
final Button startFillBtn = (Button) findViewById(R.id.btn_start_filling);
startFillBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mHeadlessProgressFragment.startProgress(100);
}
});
}
@Override
public void updateProgress(int progress) {
mProgressBar.setProgress(progress);
}
}
Answered By - Akshay Bhat 'AB'
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.