Notice
Recent Posts
Recent Comments
올해는 머신러닝이다.
[펌]LoaderManager 동작이해 본문
LoaderManager Sequence Diagram / LoaderManager flowchart /
android 3.0 이후부터 LoaderManager 를 제공한다. comparability package 를 사용하면 1.6 에서부터 사용가능하다고 한다.
LoaderManager.LoaderCallbacks<?> 을 implement 하면
ref. 6에서 LoaderManager 를 잘 설명해 주고 있다. 그리고 ref. 6의 글쓴이가 만든 source 이다.
소스는 대략적으로 아래처럼 동작한다.
AppListLoader : public class AppListLoader extends AsyncTaskLoader<List<AppEntry>>
android 3.0 이후부터 LoaderManager 를 제공한다. comparability package 를 사용하면 1.6 에서부터 사용가능하다고 한다.
Loaders 의 특징
- every Activities or Fragments : 모든 Activity 와 Fragment 에서 가능하다.(한 activity 또는 fragment 당 한개의 LoaderManager 를 갖는다. 한 개의 LoaderManager 는 여러개의 Loaders 를 가질 수 있다.)
- async data loading : data의 비동기 loading 을 을 제공한다.
- monitor and deliver the data source : data 의 source 를 모니터하면서 content 가 변경되면 전달해 준다.
- automatically reconnect : configuratoin 이 바뀐후(orientation 이 변경되는 것 등의)에 다시 만들어 질 때, 자동적으로 마지막으로 사용한 loader의 cursor 에 접속한다. 그래서 data 를 다시 query 할 필요가 없다.
만약 download 를 하고 있고, 그 progress 를 activity 에서 보여주고 있다면, download 를 하는 도중에 화면의 orientation 을 전환하면 값을 잃어버리게 된다. 이런 경우에 LoaderManager 를 이용하면 좋다고 한다.[ref. 9]
Loader Callbacks
LoaderManager 가 시작할 때 , 끝날 때 우리가 원하는 일을 시킬 수 있다. 이 일을 하는 것이 LoaderCallbacks 이다. 이 LoaderCallbacks 는 LoaderManager.initLoader() 에서 register 하게 된다.LoaderManager.LoaderCallbacks<?> 을 implement 하면
- onCreateLoader()
- onLoadFinished()
- onLoaderReset()
- onCreateLoader() : getLoaderManager().initLoader()(support library 에서는 getSupportLoaderManager().initLoader) 를 호출하면 바로 onCreateLoader() 가 호출된다.
- onLoadFinished() : onStart() 이후, AsyncTask 가 동작을 시작한다. 이 AsyncTask 동작이 끝나면, onLoadFinished() 가 호출된다. 이 곳에는 data 가 load 되고 난 후의 UI update 내용을 적으면 된다.
- onLoadReset() : android.app.LoaderManager,restartLoader()에서 새로운 loader 를 가져오고 쓰이지 않는 loader 를 destroy() 하는데 이 때 destroy() 에서 onLoadReset() 이 호출된다.
ref. 6에서 LoaderManager 를 잘 설명해 주고 있다. 그리고 ref. 6의 글쓴이가 만든 source 이다.
https://github.com/alexjlockwood/AppListLoader이 source 에서는 Fragment 가 LoaderManager.LoaderCallbacks 를 implement 하고 있으니 참고하자.
아래는 위의 소스에 대한 대략적인 sequence diagram 이다.class AppListFragment extends ListFragment implementsLoaderManager.LoaderCallbacks<List<AppEntry>>
소스는 대략적으로 아래처럼 동작한다.
- AppListFragment 에서 LoaderManager.initLoader() 를 호출(onStart() 이전에 호출해야할 듯 하다.)하면서, AppListFragment 를 LoaderCallBack 으로 등록하고,
- LoaderManager 가 onCreateLoader() 를 호출
- AppLoader() 가 만들어진다.
- Activity 가 만들어지면서 onStart() 를 호출할 때
- LoadManager.doStart() 를 호출하게 되고,
- AppLoader 의 startLoading() 을 호출한다.
- 이 때 forceLoading() 을 호출하는데,
- 이 forceLoading() (AsyncTaskLoader.onForceLoading()) 이 LoadTask() 를 만들고 Thread 를 이용해서 실행한다.
- 그러면 thread 가 doInBackground() 를 실행하게 되고,
- 이 작업이 끝난 후에 onPostExecute() 를 UI thread Handler 에게 넘기게 된다.
- 이 onPostExecute() 를 실행하면서 AppLoader 의 deliveryResult() 가 호출된다.
- 이 때 super.deliveryResult() 를 실행하면, onLoadFinished() 를 호출해 준다.
Diagrams
+--------------------------+------------------------+ | | | | +-------------------+ | | | | onCreateLoader() | | | | +--------+----------+ | | | | | | | +--------+----------+ | | | | onStartLoading() +--|-----------+ | | +-------------------+ | | | | | | | | | +--------+----------+ | | +-------------|--+ loadInBackground()| | | | | +-------------------+ | | | | | | +--------+----------+ | | | | deliverResult() | | | | +--------+----------+ | | | | | | | +--------+----------+ | | | | onLoadFinished() | | | | +-------------------+ | | +--------------------------+------------------------+
Stacks
AppListLoader : public class AppListLoader extends AsyncTaskLoader<List<AppEntry>>
UI Thread Stack trace MainActivity$AppListFragment.onCreateLoader(int, Bundle) line: 87 LoaderManagerImpl.createLoader(int, Bundle, LoaderManager$LoaderCallbacks) line: 487 LoaderManagerImpl.createAndInstallLoader(int, Bundle, LoaderManager$LoaderCallbacks) line: 496 LoaderManagerImpl.initLoader(int, Bundle, LoaderManager$LoaderCallbacks) line: 550 MainActivity$AppListFragment.onActivityCreated(Bundle) line: 77 FragmentManagerImpl.moveToState(Fragment, int, int, int, boolean) line: 892 FragmentManagerImpl.moveToState(int, int, int, boolean) line: 1083 BackStackRecord.run() line: 635 FragmentManagerImpl.execPendingActions() line: 1431 MainActivity(FragmentActivity).onStart() line: 523 Instrumentation.callActivityOnStart(Activity) line: 1133 MainActivity(Activity).performStart() line: 4475 ...
UI Thread Stack trace AppListLoader.onStartLoading() line: 129 AppListLoader(Loader).startLoading() line: 197 LoaderManagerImpl$LoaderInfo.start() line: 263 LoaderManagerImpl.doStart() line: 711 MainActivity$AppListFragment(Fragment).onStart() line: 985 MainActivity$AppListFragment(Fragment).performStart() line: 1336 FragmentManagerImpl.moveToState(Fragment, int, int, int, boolean) line: 907 FragmentManagerImpl.moveToState(int, int, int, boolean) line: 1083 FragmentManagerImpl.moveToState(int, boolean) line: 1065 FragmentManagerImpl.dispatchStart() line: 1849 MainActivity(FragmentActivity).onStart() line: 536 Instrumentation.callActivityOnStart(Activity) line: 1133 MainActivity(Activity).performStart() line: 44753 ...
Stack trace AppListLoader.loadInBackground() line: 52 AppListLoader.loadInBackground() line: 1 AppListLoader(AsyncTaskLoader).onLoadInBackground() line: 240 AsyncTaskLoader$LoadTask.doInBackground(Void...) line: 51 AsyncTaskLoader$LoadTask.doInBackground(Object[]) line: 40 ModernAsyncTask$2.call() line: 123 ...
UI Thread Stack trace AppListLoader.deliverResult(List) line: 86 AppListLoader.deliverResult(Object) line: 1 AppListLoader(AsyncTaskLoader).dispatchOnLoadComplete(AsyncTaskLoader$LoadTask, Object) line: 221 AsyncTaskLoader$LoadTask.onPostExecute(Object) line: 61 AsyncTaskLoader$LoadTask(ModernAsyncTask).finish(Object) line: 461 ...
UI Thread Stack trace MainActivity$AppListFragment.onLoadFinished(Loader, List) line: 92 MainActivity$AppListFragment.onLoadFinished(Loader, Object) line: 1 LoaderManagerImpl$LoaderInfo.callOnLoadFinished(Loader, Object) line: 425 LoaderManagerImpl$LoaderInfo.onLoadComplete(Loader, Object) line: 393 AppListLoader(Loader).deliverResult(Object) line: 103 AppListLoader.deliverResult(List) line: 111 AppListLoader.deliverResult(Object) line: 1 AppListLoader(AsyncTaskLoader).dispatchOnLoadComplete(AsyncTaskLoader$LoadTask, Object) line: 221 AsyncTaskLoader$LoadTask.onPostExecute(Object) line: 61 AsyncTaskLoader$LoadTask(ModernAsyncTask).finish(Object) line: 461 ...
See Also
References
- SimpleCursorLoader - content provider 가 필요없는 loader
- SimpleCursorLoader Example
- Android tutorial: Simple (but persistent) data storage with SQLite
- Get Started Developing For Android With Eclipse, Reloaded
- https://github.com/alexjlockwood/AppListLoader
- Life Before Loaders (part 1)
- http://code.google.com/codesearch#vhKRzqrOaj0/trunk/src/org/ray/veader/DataHelper.java&ct=rc&cd=14&q=openOrCreateDatabase&sq=
- Loaders | Android Developers
- Android Development - Example, tutorial, Source Code : Custom Loader : Loading data using Loader Manager in android asynchronously
- How to Use Loaders in Android | Grokking Android
'Android > Tip&Tech' 카테고리의 다른 글
npm 및 bower 설치.. (0) | 2014.11.18 |
---|---|
안드로이드 추천 팁 링크 (0) | 2014.11.07 |
[펌]안드로이드 Loader 활용하기 (0) | 2014.10.21 |
자바 표준 스타일 정의 (0) | 2014.09.30 |
[링크]아날로그 시계 만드는 소스 (0) | 2014.08.26 |