수색…


소개

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);
    ...
}


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow