Android
짐을 싣는 사람
수색…
소개
oncreate 메서드가 호출 될 때 백그라운드에서 데이터를로드하려는 경우 Loader는 메모리 누수를 방지하는 데 적합합니다. 예를 들어 oncreate 메소드에서 Asynctask를 실행할 때 다른 AsyncTask를 다시 실행할 액티비티가 다시 생성 될 수 있도록 화면을 회전 시키므로 이전에 실행 한 백그라운드 프로세스를 계속 수행 할 로더처럼 병렬로 실행되는 AsyncTask가 두 개가됩니다.
매개 변수
수업 | 기술 |
---|---|
LoaderManager | 하나 이상의 Loader 인스턴스를 관리하기위한 Activity 또는 Fragment 와 연관된 추상 클래스입니다. |
LoaderManager.LoaderCallbacks | 클라이언트가 LoaderManager와 상호 작용하는 콜백 인터페이스입니다. |
짐을 싣는 사람 | 비동기 적으로 데이터를로드하는 추상 클래스입니다. |
AsyncTaskLoader | 작업을 수행 하기위한 AsyncTask 를 제공하는 추상 로더. |
CursorLoader | ContentResolver를 쿼리하고 Cursor를 반환하는 AsyncTaskLoader의 하위 클래스입니다. |
비고
Android 3.0에 도입 된 로더를 사용하면 활동이나 단편에서 데이터를 비동기 적으로로드 할 수 있습니다. 로더에는 다음과 같은 특징이 있습니다.
- 모든 활동 및 단편에서 사용할 수 있습니다.
- 비동기 로딩 데이터를 제공합니다.
- 콘텐츠가 변경되면 데이터 소스를 모니터링하고 새로운 결과를 제공합니다.
- 구성 변경 후 다시 작성되면 마지막 로더의 커서에 자동으로 다시 연결됩니다. 따라서 데이터를 다시 쿼리 할 필요가 없습니다.
로더를 사용하지 않을 때
백그라운드 작업을 완료해야하는 경우 로더를 사용하면 안됩니다. Android는 Loader가 속한 Activities / Fragments와 함께 Loader를 파괴합니다. 완료 될 때까지 실행해야하는 일부 작업을 수행하려면 로더를 사용하지 마십시오. 대신 이런 종류의 서비스에 서비스를 사용해야합니다.기본 AsyncTaskLoader
AsyncTaskLoader
는 작업을 AsyncTask
하기위한 AsyncTask
를 제공하는 추상 Loader
입니다.
여기 몇 가지 기본 구현 :
final class BasicLoader extends AsyncTaskLoader<String> {
public BasicLoader(Context context) {
super(context);
}
@Override
public String loadInBackground() {
// Some work, e.g. load something from internet
return "OK";
}
@Override
public void deliverResult(String data) {
if (isStarted()) {
// Deliver result if loader is currently started
super.deliverResult(data);
}
}
@Override
protected void onStartLoading() {
// Start loading
forceLoad();
}
@Override
protected void onStopLoading() {
cancelLoad();
}
@Override
protected void onReset() {
super.onReset();
// Ensure the loader is stopped
onStopLoading();
}
}
일반적으로 Loader
는 액티비티의 onCreate()
메소드 내에서 또는 프래그먼트의 onActivityCreated()
내에서 초기화됩니다. 또한 일반적으로 activity 또는 fragment는 LoaderManager.LoaderCallbacks
인터페이스를 구현합니다.
public class MainActivity extends Activity implements LoaderManager.LoaderCallbacks<String> {
// Unique id for loader
private static final int LDR_BASIC_ID = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Initialize loader; Some data can be passed as second param instead of Bundle.Empty
getLoaderManager().initLoader(LDR_BASIC_ID, Bundle.EMPTY, this);
}
@Override
public Loader<String> onCreateLoader(int id, Bundle args) {
return new BasicLoader(this);
}
@Override
public void onLoadFinished(Loader<String> loader, String data) {
Toast.makeText(this, data, Toast.LENGTH_LONG).show();
}
@Override
public void onLoaderReset(Loader<String> loader) {
}
}
이 예에서 로더가 완료되면 결과와 함께 토스트가 표시됩니다.
캐시가있는 AsyncTaskLoader
동일한 데이터를 여러 번로드하지 않으려면로드 된 결과를 캐시하는 것이 좋습니다.
캐시를 무효화하려면 onContentChanged()
를 호출해야합니다. 로더가 이미 시작된 경우 forceLoad()
가 호출되고, 그렇지 않으면 (로더가 중지 상태 인 경우) 로더가 takeContentChanged()
확인을 사용하여 내용 변경을 이해할 수 있습니다.
비고 : onContentChanged()
는 프로세스의 메인 스레드에서 호출되어야합니다.
Javadocs는 takeContentChanged ()에 대해 다음과 같이 말합니다.
로더의 내용이 정지하고있는 동안 변경되었는지 여부를 나타내는 현재 플래그를 가져옵니다. 있었다면 true를 반환하고 플래그를 지 웁니다.
public abstract class BaseLoader<T> extends AsyncTaskLoader<T> {
// Cached result saved here
private final AtomicReference<T> cache = new AtomicReference<>();
public BaseLoader(@NonNull final Context context) {
super(context);
}
@Override
public final void deliverResult(final T data) {
if (!isReset()) {
// Save loaded result
cache.set(data);
if (isStarted()) {
super.deliverResult(data);
}
}
}
@Override
protected final void onStartLoading() {
// Register observers
registerObserver();
final T cached = cache.get();
// Start new loading if content changed in background
// or if we never loaded any data
if (takeContentChanged() || cached == null) {
forceLoad();
} else {
deliverResult(cached);
}
}
@Override
public final void onStopLoading() {
cancelLoad();
}
@Override
protected final void onReset() {
super.onReset();
onStopLoading();
// Clear cache and remove observers
cache.set(null);
unregisterObserver();
}
/* virtual */
protected void registerObserver() {
// Register observers here, call onContentChanged() to invalidate cache
}
/* virtual */
protected void unregisterObserver() {
// Remove observers
}
}
다시로드 중
이전 데이터를 무효화하고 기존의 로더를 다시 시작하려면 restartLoader()
메소드를 사용할 수 있습니다.
private void reload() {
getLoaderManager().reastartLoader(LOADER_ID, Bundle.EMPTY, this);
}
번들을 사용하여 매개 변수 전달
Bundle을 통해 매개 변수를 전달할 수 있습니다.
Bundle myBundle = new Bundle();
myBundle.putString(MY_KEY, myValue);
onCreateLoader에서 값 가져 오기 :
@Override
public Loader<String> onCreateLoader(int id, final Bundle args) {
final String myParam = args.getString(MY_KEY);
...
}