Несколько погрузчиков с одинаковой активностью
У меня есть два настраиваемых загрузчика, унаследованных от AsyncTaskLoader
, которые я хотел бы использовать в своей деятельности. Каждый из них возвращает результат другого типа.
Чтобы использовать свою активность для обратного вызова, я должен реализовать два интерфейса:
implements LoaderCallbacks<GetSyncListDataResult>, LoaderCallbacks<ErrorResult>
Однако, пытаясь реализовать требуемые методы в том же классе, я в конечном итоге
ошибка повторяющегося метода и ошибка стирания (???):
// Methods for the first loader
public Loader<GetSyncListDataResult> onCreateLoader(int ID, Bundle bundle) ...
public void onLoaderReset(Loader<GetSyncListDataResult> loader) ...
public void onLoadFinished(Loader<GetSyncListDataResult> loader, GetSyncListDataResult result) ...
// Methods for the second loader
public Loader<ErrorResult> onCreateLoader(int ID, Bundle bundle) ...
public void onLoaderReset(Loader<ErrorResult> loader) ...
public void onLoadFinished(Loader<ErrorResult> loader, ErrorResult result) ...
Очевидно, что методы сталкиваются, и мне нужен простой способ решить эту проблему.
Каким будет правильный способ решения этого вопроса?
Ответы
Ответ 1
Правильный ответ соответствует комментарию @dymmeh, т.е. не для Activity
реализовать два интерфейса LoaderCallbacks
, но для того, чтобы активность содержала две реализации LoaderCallbacks
. В качестве примера: инициализируйте ваши поля LoaderCallbacks
в вашей деятельности...
private LoaderCallbacks<GetSyncListDataResult> dataResultLoaderListener
= new LoaderCallbacks<GetSyncListDataResult>() { ...methods here... };
private LoaderCallbacks<ErrorResult> errorResultLoaderListener
= new LoaderCallbacks<ErrorResult>() { ...methods here... };
... и объявить идентификаторы вашего загрузчика...
private static final int DATA_RESULT_LOADER_ID = 1;
private static final int ERROR_RESULT_LOADER_ID = 2;
... и затем инициализируйте ваши загрузчики...
getLoaderManager().initLoader(DATA_RESULT_LOADER_ID, dataResultBundle, dataResultLoaderListener);
getLoaderManager().initLoader(ERROR_RESULT_LOADER_ID, errorResultBundle, errorResultLoaderListener);
... Готово!
Ответ 2
class YourActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks {
// you still implements LoaderManager.LoaderCallbacks but without add <returnType>
//and you have to cast the data into your needed data type in onLoadFinished()
Private int loader1 = 1;
private int loader2 =2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
getSupportLoaderManager().initLoader(REVIEW_LOADER, null, this);
getSupportLoaderManager().initLoader(REVIEW_LOADER, null, this);
}
@Override
public Loader onCreateLoader(int id, Bundle args) {
if (id == loader1 ) {
//YourLoaderClass1 is you loaderClass where you implement onStartLoading and loadingInBackground()
return new YourLoaderClass1();
} else if (id == loader2 ) {
return new YourLoaderClass2();
}
return null;
}
@Override
public void onLoadFinished(Loader loader, Object data) {
int id = loader.getId();// find which loader you called
if (id == loader1 ) {
yourMethod1((List< >) data); // eg. cast data to List<String>
} else if (id == loader2 ) {
yourMethod1((String) data); // eg. cast data to String
}
}
@Override
public void onLoaderReset(Loader loader) {
int id = loader.getId();
if (id == loader1 ) {
} else if (id == loader2 ) {
}
}
}
Мой пример Github
Ответ 3
На самом деле проще, если вы реализуете LoaderManager.LoaderCallbacks<T>
в своем классе Activity и, используя определенные идентификаторы загрузчиков, манипулируете результатом.
Таким образом, ваш код станет более читабельным и функциональным (поскольку больше не будет дублирования реализаций интерфейса обратных вызовов внутреннего загрузчика).
Например:
public class JobListActivity extends AppCompatActivity implements LoaderManager.LoaderCallbacks<NetworkResult> {
public static final int SUBMIT_RISK_ASSESSMENT_LOADER = 546;
public static final int LOAD_RISK_ASSESSMENT_LOADER = 1546;
public Loader<NetworkResult> onCreateLoader(int id, @Nullable Bundle args) {
if (id == SUBMIT_RISK_ASSESSMENT_LOADER) {
return new NetworkLoader( this, args.getString( NetworkLoader.URL_EXTRA ), NetworkLoader.POST, args.getString( BODY ), false ));
} else if (id == LOAD_RISK_ASSESSMENT_LOADER) {
return new NetworkLoader( this, args.getString( NetworkLoader.URL_EXTRA ), NetworkLoader.GET, null, false ) );
}
return null;
}
@Override
public void onLoadFinished(@NonNull Loader<NetworkResult> loader, NetworkResult data) {
if (data == null) {
return;
}
Crashlytics.log( Log.INFO, TAG, "onLoadFinished with data [" + data + "]" );
if (loader.getId() == SUBMIT_RISK_ASSESSMENT_LOADER) {
doSemethingElse(data);
} else if (loader.getId() == LOAD_RISK_ASSESSMENT_LOADER) {
doSemethingElse(data);
}
LoaderManager.getInstance( this ).destroyLoader( loader.getId() );
}
Ответ 4
Это необязательно. Внедрение LoaderManager.LoaderCallbacks. Затем, каждый раз, когда вы инициализируете загрузчик, дайте ему уникальный идентификатор. В обратных вызовах вы можете обнаружить идентификатор загрузчика, который вызвал обратный вызов, и предпринять соответствующие действия.
то есть
class MyLoader extends Activity implements LoaderManager.LoaderCallbacks<GetSyncDataResult> {
...
private static final int LOADER1 = 1;
private static final int LOADER2 = 2;
...
getLoaderManager().initLoader(LOADER1, null, this);
...
getLoaderManager().initLoader(LOADER2, null, this);
...
public Loader<GetSyncDataResult> onCreateLoader(int loaderId, Bundle args) {
switch (loaderId) {
case LOADER1: ...
case LOADER2: ...
}
...
и т.д.