Friday, May 6, 2016

AsyncTask deal with Orientation Changes in Android



In this blog I want to talk about various way to deal with AsyncTask on orientation and also want to explain brief details about Loaders. Loaders introduce from android 3.0 and it is more convenient in the situation where screen orientation getting change.

AsyncTask deal with Orientation Changes in Android:

AsyncTask is very common in android for background task like web service call, downloading data, logging in to application etc.
Implementing an AsyncTask is fairly a simple job, the big challenge is how to handle it properly when an orientation change occurs.
The reason behind difficult to handle AsyncTask with orientation, because when orientation get change the activity and UI elements is also recreated and context with the Asynctask was started that no more exists when task will get complete. In this situation if AsyncTask want to update any UI element then it doesn’t get any reference and Exception occurs.
If situation is like Asynctask is getting started and this is not going to update any UI elements just do a background task like data download and it execute with application context means there is no dependency with UI and activity once start then there is no occurrence of any exception and it completes task successfully because it works in separate worker thread.
There is few solution to deal with AsyncTask in orientation change  

Put AsyncTask in Fragment:

 Fragments probably is the cleanest way to handle configuration changes. By default, Android destroys and recreates the fragments just like activities, however, fragments have the ability to retain their instances, simply by calling setRetainInstance(true), in one of its callback methods, for example in the onCreate()
public class TestFragment extends Fragment implements TaskListener, OnClickListener {

    private ProgressDialog progressDialog;
    private boolean isTaskRunning = false;
    private AsyncTaskExample asyncTask;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setRetainInstance(true);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        /* In case we are returning here from a screen orientation and the AsyncTask is still working, re-create and display the progress dialog.*/
        if (isTaskRunning) {
            progressDialog = ProgressDialog.show(getActivity(), "Loading", "Please wait ");
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_layout, container, false);
        Button button = (Button) view.findViewById(R.id.button1);
        button.setOnClickListener(this);
        return view;
    }

    @Override
    public void onClick(View v) {
        if (!isTaskRunning) {
            asyncTask = new AsyncTaskTestExample(this);
            asyncTask.execute();
        }
    }

    @Override
    public void onTaskStarted() {
        isTaskRunning = true;
        progressDialog = ProgressDialog.show(getActivity(), "Loading", "Please wait");
    }

    @Override
    public void onTaskFinished(String result) {
        if (progressDialog != null) {
            progressDialog.dismiss();
        }
        isTaskRunning = false;
    }

    @Override
    public void onDetach() {
        if (progressDialog != null && progressDialog.isShowing()) {
            progressDialog.dismiss();
        }
        super.onDetach();
    }
}


Lock Screen Orientation:

There is two way to lock orientation
1)      Lock from AndroidMenifest: permanently locking the screen orientation of the activity, specifying the screenOrientation attribute in the AndroidManifest with portrait or landscape values
<activity android:screenOrientation="portrait”   />

2)      Lock in Acivity: temporarily locking the screen in onPreExecute(), and unlocking it in onPostExecute(), thus preventing any orientation change while the AsyncTask is working.

private void lockScreenOrientation() {
    int currentOrientation = getResources().getConfiguration().orientation;
    if (currentOrientation == Configuration.ORIENTATION_PORTRAIT) {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    } else {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    }
}

private void unlockScreenOrientation() {
    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
}



Prevent the Activity from being recreated:

In this approach activity prevents itself to recreate. This is the easiest way to handle configuration changes, but the less advised. The only thing you need to do is to specify the configChanges attribute.
This approach  is not recommended, and this is clearly stated in the Android documentation  ‘Using this attribute should be avoided and used only as a last-resort’

<activity
   android:configChanges="orientation|keyboardHidden"
   android:name=".Activity" />


Loaders:

Loaders are another way to handle background task with orientation changes.
Introduced in Android 3.0, loaders make it easy to asynchronously load data in an activity or fragment. Loaders have these characteristics:
1)      They are available to every Activity and Fragment.
2)      They provide asynchronous loading of data.
3)      They monitor the source of their data and deliver new results when the content changes.
4)      They automatically reconnect to the last loader's cursor when being recreated after a configuration change. Thus, they don't need to re-query their data.
The below is the code snippet handles orientation changes for background task.

// call this to re-connect with an existing loader (work after screen configuration changes)
                        LoaderManager lm = getLoaderManager();
                        if (lm.getLoader(0) != null) {
                                    lm.initLoader(0, null, this);
                        }



            





12 comments:

  1. "AsyncTask: Dealing with Orientation Changes in Android" pertains to managing the behavior of AsyncTask, How Activate Minecraft a class used in Android for performing background operations.

    ReplyDelete