Android 3.0 에서 도입 한 비동기 로드 메커니즘 Loader
9675 단어 Android비동기 로드 메커니즘Loader
Loader 의 장점 사용 하기
만약 우리 가 네트워크 에서 데 이 터 를 가 져 올 필요 가 있다 면,일반적인 방법 은 하위 스 레 드 Thread+Handler 를 사용 하거나 AsyncTask 를 사용 하여 처리 하 는 것 입 니 다.
Thread+Handler 방법 은 간단 하고 직관 적 이지 만 번 거 로 울 수 있 습 니 다.Handler 서브 클래스 를 스스로 실현 하고 스 레 드 를 만 들 며 Handler 의 생명 주 기 를 관리 해 야 합 니 다.
AsyncTask 는 스 레 드 와 Handler 를 스스로 관리 할 필요 가 없 이 간단 합 니 다.그러나 AsyncTask 의 라 이 프 사이클 을 관리 하려 면 Activity 종료 시 상황 을 처리 해 야 합 니 다.그렇지 않 으 면 이상 이나 메모리 유출 이 발생 할 수 있 습 니 다.
Loader 를 사용 하면 스 레 드 와 Handler 의 생 성 과 소각 에 관심 을 가 질 필요 도 없고 데이터 의 전체 생명 주 기 를 스스로 관리 할 필요 도 없습니다.Loader 체 제 는 자동 으로 우 리 를 도와 처리 할 것 입 니 다.우리 가 유일 하 게 처리 해 야 할 것 은 데이터 자체 다.
Loader 에서 사용 하 는 절차:
Fragment Activity 나 Fragment 를 만 들 고 LoaderManager 의 인 스 턴 스 를 가지 고 Loader 를 실현 합 니 다.데이터 원본 에서 돌아 온 데 이 터 를 불 러 와 LoaderManager 를 실현 합 니 다.LoaderCallbacks 인터페이스 에서 데 이 터 를 보 여 주 는 데이터 원본,예 를 들 어 ContentProvider,서버 에서 보 낸 데이터 등 몇 가지 관련 된 LoaderManager 를 실현 합 니 다.
Loader 인 스 턴 스 를 관리 하고 Fragment Activity 나 Fragment 와 연결 합 니 다.
Activity 나 Fragment 에 유일한 LoaderManager 인 스 턴 스 가 있 습 니 다.
하나의 LoaderManager 인 스 턴 스 는 여러 개의 Loader 인 스 턴 스 를 관리 할 수 있 습 니 다.
Fragment Activity 나 Fragmeng 에서 getSupportLoaderManager()를 사용 하여 LoaderManager 인 스 턴 스 를 가 져 올 수 있 습 니 다.
initLoader()또는 restartLoader()방법 으로 데 이 터 를 불 러 올 수 있 습 니 다.
//0, ID, , Loader
//null, Bundle , Loader
//LoaderCallbacks,LoaderManager Loader , LoaderManager.LoaderCallbacks
getSupportLoaderManager().initLoader(0, null, new LoaderCallbacks<D>());
LoaderManager.LoaderCallbacksLoader Manager 는 Loader 의 다양한 상황 에 대한 리 셋 인터페이스 로 세 가지 리 셋 방법 을 포함 합 니 다.
onCreateLoader(int,Bundle)
Loader 대상 을 직접 만들어 야 합 니 다.int 는 Loader 의 유일한 표지 이 고 Bundle 은 Loader 의 구조 적 매개 변수 이 며 비어 있 습 니 다.
...
new LoaderManager.LoaderCallbacks<String>() {
@Override
public Loader<String> onCreateLoader(int id, Bundle args) {
return new MyLoader();
}
...
}
onLoadFinished(LoaderLoaderManager 가 데 이 터 를 불 러 왔 을 때 이 방법 을 되 돌려 줍 니 다.사용자 에 게 UI 로 데 이 터 를 보 여 줍 니 다.D 는 범용 이 고 실제 상황 에 따라 필요 한 데이터 형식 으로 설정 합 니 다.initLoader()LoaderCallbacks
new LoaderManager.LoaderCallbacks<String>() {
...
@Override
public void onLoadFinished(Loader<String> loader, String data) {
show(data);
}
...
}
onLoaderReset(Loader이전에 만 든 Loader 인 스 턴 스 가 리 셋 되 었 을 때 이 방법 을 되 돌려 줍 니 다.이 때 는 관련 데 이 터 를 제거 해 야 합 니 다.
new LoaderManager.LoaderCallbacks<String>() {
...
@Override
public void onLoaderReset(Loader<String> loader) {
show(null);
}
...
}
Loader데이터 원본 에서 데 이 터 를 가 져 오고 데 이 터 를 불 러 옵 니 다.추상 류 로 서 하위 클래스 를 스스로 실현 해 야 합 니 다.
공식 적 으로 이 루어 진 두 가지 키 를 사용 하거나
AsyncTask Loader(이 를 계승 할 때 구 덩이 를 만 날 수 있 습 니 다.아래 분석 참조)
비동기 처리 데이터 가 져 오기 CursorLoader
ContentProvider 가 되 돌려 준 데 이 터 를 처리 하여 AsyncTaskLoader 가 만난 구덩이
먼저 MyAsyncTaskLoader 를 사용자 정의 하고 AsyncTaskLoader 를 계승 하면 매개 변 수 를 Context 로 하 는 구조 방법 과 loadInBackground()추상 적 인 방법 을 실현 해 야 합 니 다.
// AsyncTaskLoader , , String
public class MyAsyncTaskLoader extends AsyncTaskLoader<String>{
public MyAsyncTaskLoader(Context context) {
super(context);
}
@Override
public String loadInBackground() {
//
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//
return new String("MyAsyncTaskLoader Test Result");
}
}
FragmentActivity 만 들 기
public class BaseActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks{
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.base_activity_layout);
// addFragment();
log("onCreate");
loadData();
}
protected void loadData(){
Log.e(getClassName(),"call");
getSupportLoaderManager().initLoader(0, null, this);
}
protected String getClassName(){
return getClass().getSimpleName();
}
@Override
public Loader onCreateLoader(int id, Bundle args) {
Log.e(getClassName(),"onCreateLoader");
return new MyAsyncTaskLoader(BaseActivity.this);
}
@Override
public void onLoadFinished(Loader loader, Object data) {
Log.e(getClassName(),"data:"+data);
}
@Override
public void onLoaderReset(Loader loader) {
}
}
실행 중 로그 값 이 onCreate,call,onCreateLoader 로 인쇄 되 어 있 는 것 을 발 견 했 습 니 다.예상 되 는 MyAsyncTaskLoader Test Result 는 출력 되 지 않 았 습 니 다.즉,onLoadFinished 는 반전 되 지 않 았 습 니 다.디 버 깅 결과 MyAsyncTaskLoader 의 loadInBackground()방법 도 실행 되 지 않 았 습 니 다.이게 어떻게 된 거 죠?
그러면 소스 코드 를 볼 수 밖 에 없습니다.여기 서 사용 하 는 것 은 모두 슈퍼 port-v4 가방 입 니 다.
AsyncTask Loader 소스 코드 를 보면 loadInBackground()방법 이 abstract 형식 임 을 알 수 있 습 니 다.호출 된 곳 은 LoadTask 라 는 내부 클래스 에 있 습 니 다.
// ModernAsyncTask AsyncTask
final class LoadTask extends ModernAsyncTask<Void, Void, D> implements Runnable {
....
@Override
protected D doInBackground(Void... params) {
...
D data = AsyncTaskLoader.this.onLoadInBackground();
...
}
.....
}
또한 AsyncTask Loader 의 전역 변수 입 니 다.
public abstract class AsyncTaskLoader<D> extends Loader<D> {
....
volatile LoadTask mTask;
....
}
mTask 실례 화 및 실 행 된 곳 은 onForceLoad()방법 에서
...
@Override
protected void onForceLoad() {
...
mTask = new LoadTask();
...
executePendingTask();
}
...
void executePendingTask() {
...
if (mUpdateThrottle > 0) {
...
mHandler.postAtTime(mTask, mLastLoadCompleteTime+mUpdateThrottle);
return;
}
}
...
mTask.executeOnExecutor(mExecutor, (Void[]) null);
}
}
mHandler.postAtTime 이나 mTask.execute OnExecutor 두 곳 이 바로 Task Loader 를 실행 하 는 곳 이 고 doInBackground()방법 으로 호출 됩 니 다.이 쯤 에서 사용자 정의 MyAsyncLoader 의 loadInBackground()가 실행 되 지 않 았 다 고 추측 할 수 있 습 니 다.그러면 onForceLoad()도 실행 되 지 않 았 을 것 입 니 다.
이 단 서 를 따라 이 onForceLoad()가 어디에서 호출 되 었 는 지 찾 아 보 세 요.AsyncLoader 의 부모 클래스 Loader 의 forceLoad()에서 호출 된 것 으로 밝 혀 졌 습 니 다.
public class Loader{
...
public void forceLoad() {
onForceLoad();
}
...
}
그리고 주석 을 보 니 이 방법 은 loader 가 시 작 될 때 만 호출 할 수 있 을 뿐 실 마 리 를 찾 지 못 했 습 니 다.갑자기 CursorLoader 에 문제 가 없 는 것 같 습 니 다.forceLoad()가 호출 되 었 는 지 찾 아 보 니 역시 있 었 습 니 다!onStart Loading()이라는 방법 에 있 습 니 다.그리고 여기 서 만 호출 됩 니 다!
public class CursorLoader extends AsyncTaskLoader<Cursor> {
...
@Override
protected void onStartLoading() {
if (mCursor != null) {
deliverResult(mCursor);
}
if (takeContentChanged() || mCursor == null) {
forceLoad();
}
}
...
}
그럼 이 걸 따라 해 볼 게 요.정말 되 는 지 아 닌 지.MyAsyncLoader 의 코드 수정 은 다음 과 같 습 니 다.
// AsyncTaskLoader , , String
public class MyAsyncTaskLoader extends AsyncTaskLoader<String>{
public MyAsyncTaskLoader(Context context) {
super(context);
}
//
@Override
protected void onStartLoading() {
forceLoad();
}
@Override
public String loadInBackground() {
//
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//
return new String("MyAsyncTaskLoader Test Result");
}
}
실행 해 보 니 정말 출력 이 가능 합 니 다!문 제 는 해 결 된 것 같 습 니 다.마지막 행동 출력 결과
문 제 는 해결 되 었 습 니 다.하지만 의문 이 있 습 니 다.이 onStart Loading()은 어디에서 호출 되 었 습 니까?아무래도 소스 코드 를 봐 야 겠 어 요.
getSupportLoaderManager().initLoader(0,null,this)를 분석 한 결과 마지막 으로 onStartLoading()으로 호출 되 는 것 으로 나 타 났 다.
요약 하면 다음 과 같 습 니 다.원본 코드 를 대조 하여 볼 수 있 습 니 다.
LoaderManager LoaderManagerImpl
init() LoaderInfo info
info = createAndInstallLoader(id, args, (LoaderManager.LoaderCallbacks<Object>)callback); createAndInstallLoader
mCallbacks.onLoadFinished(loader, data); onLoadFinished
createLoader(id, args, callback) createLoader
installLoader(info); installLoader
info.start(); start
mLoader.startLoading(); startLoading
onStartLoading();
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Bitrise에서 배포 어플리케이션 설정 테스트하기이 글은 Bitrise 광고 달력의 23일째 글입니다. 자체 또는 당사 등에서 Bitrise 구축 서비스를 사용합니다. 그나저나 며칠 전 Bitrise User Group Meetup #3에서 아래 슬라이드를 발표했...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.