У меня возникают серьезные трудности с пониманием того, как я могу заставить некоторых дочерних элементов AsyncTask, объявленных и созданных в основном потоке, ожидать, пока экземпляр дочернего объекта Service достигнет определенного состояния.
В качестве примеров кода здесьсоответствующая часть для обслуживания;этот код выполняет то, что ожидалось: получает ответ JSON и удерживает его.
public class MyService extends Service {
private boolean received = false;
private string url = "http://someserver.mine/get-data-in-json-format";
// [...]
@Override
public void onCreate() {
doHttpJsonQuery();
}
public boolean responseReceived() {
return this.received;
}
public List<MyModel> getResponseAsObject() {
if (!this.received) return new ArrayList<MyModel>;
// Many code lines that convert the data into a list.
// [...]
return the_list;
}
// [...]
private void doHttpJsonQuery() {
OkHttpClient client = new OkHttpClient.Builder()
.build();
Request request = new Request.Builder()
.url(url)
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
call.cancel();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
final String myResponse = response.body().string();
//...and some code to hold data as JSONArray
//[...]
}
});
this.received = true;
}
}
Эта служба работает;хорошо.Затем из другого класса (целью которого будет обрабатывать постоянство, вставляя полученные данные в локальную базу данных комнат), я пытаюсь сделать следующее (вот где мой ум поражен):
public class DataRepository {
private MyRoomDatabase db;
private MyModelDao mModelDao;
// I'm skipping irrelevant code on purpose
// [...]
public DataRepository(Application application) {
db = MyRoomDatabase.getDatabase(application);
mModelDao = db.myModelDao();
// [...]
// Here I instance a subclass of ContextWrapper(i named it RemoteDataSource) which
// responsability will be handling different Services for making HTTP operations
mRemoteDataSource = new RemoteDataSource(application.getApplicationContext());
// It holds a reference to MyService. It has some public methods, like this one, to
// control the referenced Service from outside with some encaspsulation
mRemoteDataSource.startMyService();
// Instantiating a private nested class...
PopulateDbAsync mPopulateDbAsync = new PopulateDbAsync(db);
mPopulateDbAsync.doInBackground();
}
// [...]
// Here is the failing code
private class PopulateDbAsync extends AsyncTask<Void, Void, Void> {
PopulateDbAsync(MyRoomDatabase db) {}
@Override
protected Void doInBackground(final Void... params) {
MyService mService = mRemoteDataSource.getMyService();
if (mService == null) {
// This doesn't happen at all right now...
Log.e("MY_ERROR","DataRepository.PopulateDbAsync --> MyService from RemoteDataSource is NULL!!!!");
}
List<MyModel> the_list = mService.getResponseAsObject();
if (the_list == null) {
// HERE! I obtain the NullReferenceException here.
// I am confused about how would I avoid this flaw in my code
Log.e("MY_ERROR", "DataRepository.PopulateDbAsync --> error: response isn't ready yet.");
}
for (MyModel i_model : the_list) {
Log.d("MY_LOG", "DataRepository.PopulateDbAsync --> Inserting data in local DB...");
mModelDao.insert(i_model);
}
return null;
}
}
}
Подводя итог:моя проблема в том, что я всегда получу NullReferenceException
в этой строке:
for (MyModel i_model : the_list) {
Я не знаком с многопоточностью, асинхронными операциями и параллельным выполнением.В течение двух недель я читал много разных документов в Интернете, как с официального сайта Android, так и с других сайтов, пытаясь выяснить это ... «AsyncTask не подходит для выполнения таких операций» ..Итак, какую инфраструктуру я должен реализовать, мне было интересно ... я должен использовать обработчики, потоки, мессенджеры или что?Чем больше я читаю, тем больше путаюсь.Как будто у меня проблема Analysis Paralysis ...
Большинство примеров, которые я там обнаружил, содержат слишком подробные примеры кода о том, как реализовать многопоточность и параллельное выполнение;пока я читаю их и пытаюсь понять, как реализовать эти структуры в моем коде, я просто застреваю;Кроме того, с таким количеством классов, которые я могу выбрать, я еще больше запутался ...
Из-за того, что HTTP-вызов должен выполняться асинхронно (и время ответа не всегда будет одинаковым), я пытаюсьвыяснить, как заставить фрагмент кода, который вызывает NullReferenceException
«ожидание», чтобы MyService завершил свою работу перед началом выполнения;Циклы while
не будут работать, потому что это нарушит жизненный цикл основного потока.«Знать», завершила ли Служба свою задачу или нет, было бы так же просто, как использовать логический метод responseReceived
.Основная идея заключается в том, что каждый раз, когда новые данные получают через HTTP, обновляя им RoomDatabase, а MainActivity будет отображать текущие локальные данные (если они есть) или пустой список, если ничего еще нет).
Итак, когда я получу его, я пойму, как правильно провести рефакторинг всей структуры кода, чтобы начать добавлять больше Service
дочерних экземпляров в мой класс RemoteDataSource
, который я создал с идеей иметь все дочерние элементы Service, которые будут использоватьOkHttp
для выполнения HTTP-коммуникаций, объединенных в один класс для лучшей организации.
Каков правильный способ добиться того, что я ищу по этому поводу?Может ли кто-нибудь предоставить какой-нибудь короткий пример, объясняющий структуру кода, которая мне понадобится для чего-то подобного?Примеры с пустыми блоками, содержащими комментарии, такие как «код, который нужно выполнить, когда будет готов», были бы хорошими, поэтому я могу разобраться с этим.
Вопрос, затронутый здесь, связан с тем же проектом, который заставил меня опубликовать этот другойвопрос несколько недель назад;Я читал здесь и там, выполняя некоторые методики проб и ошибок и исправляя некоторые проблемы с кодом тут и там;однако я задаю здесь другой вопрос;поиск ответа на этот вопрос, вероятно, был бы первым шагом к выяснению ответа на другой вопрос.
URL Ссылки на документацию, которую я читал
Часть документации, на которую я обращалсячтение (но не ограничиваясь):