Получение данных из Cloud Firestore с помощью AsynkTaskLoader в Android

Я новичок в Android и Firebase, и у меня возникла странная ошибка, которую я не понимаю. У меня есть RecyclerView, который должен отображать список строк с датами, за которыми следует число. Теперь я хочу получить данные из Cloud Firestore и отобразить их. Для этой цели я использую AsyncTaskLoader, а в loadInBackground() я получаю данные из Cloud Firestore. Теперь, когда я запускаю действие, отображается сообщение об ошибке (и оно будет продолжать вести себя таким образом, независимо от того, сколько раз я нажимал кнопку обновления). Однако, если я выключу экран, а затем включу, он показывает данные так, как я хочу. Ниже мой код

public class MeasureListActivity extends AppCompatActivity implements
    MeasuresAdapter.MeasuresAdapterOnClickHandler,
    LoaderManager.LoaderCallbacks<String[]> {

private RecyclerView mRecyclerView;

private FirebaseAuth mAuth;
private MeasuresAdapter mMeasuresAdapter;

private TextView mErrorMessageDisplay;

private ProgressBar mLoadingIndicator;

private static final int MEASURES_LOADER_ID = 0;


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    /* Use AppCompatActivity's method getMenuInflater to get a handle on the menu inflater */
    MenuInflater inflater = getMenuInflater();
    /* Use the inflater's inflate method to inflate our menu layout to this menu */
    inflater.inflate(R.menu.measures_list, menu);
    /* Return true so that the menu is displayed in the Toolbar */
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId();

    if (id == R.id.action_refresh) {
        invalidateData();
        getSupportLoaderManager().restartLoader(MEASURES_LOADER_ID, null, this);
        return true;
    }
    return super.onOptionsItemSelected(item);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_measure_list);

    mAuth = FirebaseAuth.getInstance();

    mRecyclerView = (RecyclerView) findViewById(R.id.recyclerview_measures);

    mErrorMessageDisplay = (TextView) findViewById(R.id.tv_error_message_display);

    LinearLayoutManager layoutManager
            = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);

    mRecyclerView.setLayoutManager(layoutManager);

    mRecyclerView.setHasFixedSize(true);

    mMeasuresAdapter = new MeasuresAdapter(this);

    mRecyclerView.setAdapter(mMeasuresAdapter);

    mLoadingIndicator = (ProgressBar) findViewById(R.id.pb_loading_indicator);

    int loaderId = MEASURES_LOADER_ID;

    LoaderManager.LoaderCallbacks<String[]> callback = MeasureListActivity.this;

    Bundle bundleForLoader = null;

    getSupportLoaderManager().initLoader(loaderId, bundleForLoader, callback);
}

@Override
public Loader<String[]> onCreateLoader(int id, final Bundle loaderArgs) {



    return new AsyncTaskLoader<String[]>(this) {

        String[] mWMeasuresData = null;

        @Override
        protected void onStartLoading() {
            if (mWMeasuresData != null) {
                deliverResult(mWMeasuresData);
            } else {
                mLoadingIndicator.setVisibility(View.VISIBLE);
                forceLoad();
            }
        }


        private String[] aux;
        @Override
        public String[] loadInBackground() {


            FirebaseFirestore db = FirebaseFirestore.getInstance();

            db.collection("medidas").whereEqualTo("id_user", "3Aq3g0czkarT8GIbyESV").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
                @Override
                public void onComplete(@NonNull Task<QuerySnapshot> task) {
                    if (task.isSuccessful()) {
                        QuerySnapshot snapshot = task.getResult();
                        int tam = snapshot.getDocuments().size();
                        aux = new String[tam];
                        for (int i = 0; i < tam; i++) {
                            String temp = "";
                            DocumentSnapshot doc = snapshot.getDocuments().get(i);
                            temp += doc.get("fecha") + " ";
                            temp += doc.get("valor");
                            aux[i] = temp;
                        }

                    }
                }
            });

            return aux;
        }


        public void deliverResult(String[] data) {
            mWMeasuresData = data;
            super.deliverResult(data);
        }
    };
}

@Override
public void onLoadFinished(Loader<String[]> loader, String[] data) {
    mLoadingIndicator.setVisibility(View.INVISIBLE);
    mMeasuresAdapter.setMeasuresData(data);
    if (null == data) {
        showErrorMessage();
    } else {
        showMeasuresDataView();
    }
}

@Override
public void onLoaderReset(Loader<String[]> loader) {

}


private void invalidateData() {
    mMeasuresAdapter.setMeasuresData(null);
}


private void showMeasuresDataView() {
    /* First, make sure the error is invisible */
    mErrorMessageDisplay.setVisibility(View.INVISIBLE);
    /* Then, make sure the weather data is visible */
    mRecyclerView.setVisibility(View.VISIBLE);
}

private void showErrorMessage() {
    /* First, hide the currently visible data */
    mRecyclerView.setVisibility(View.INVISIBLE);
    /* Then, show the error */
    mErrorMessageDisplay.setVisibility(View.VISIBLE);
}
@Override
public void onClick(String measure) {
    Context context = this;
    Class destinationClass = DetailMeasureActivity.class;
    Intent intentToStartDetailActivity = new Intent(context, destinationClass);
    intentToStartDetailActivity.putExtra(Intent.EXTRA_TEXT, measure);
    startActivity(intentToStartDetailActivity);
}

}

Вы можете мне с этим помочь? ... заранее спасибо

Вам действительно не нужно использовать AsyncTaskLoader с Firestore. API-интерфейсы Firestore уже являются асинхронными, и повторить выборку не проблема, потому что сначала она будет извлекаться из кеша. Использование загрузчика просто добавляет намного больше кода без уважительной причины.

Doug Stevenson 07.10.2018 06:56
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
1
101
1

Ответы 1

Прежде всего, я думаю, что когда вы вызываете этот блок кода:

 mLoadingIndicator.setVisibility(View.VISIBLE);
            forceLoad();

Вы также должны скрыть представление сообщения об ошибке.

Кроме того, если серьезно, вам не нужен AsyncTaskLoader для получения данных из firestore, firebase firestore уже выполняет фоновую работу за вас.

Чтобы полностью понять причину проблемы, вам необходимо понимать жизненный цикл своей активности и добавлять журналы для отметки критических событий, которые помогут вам узнать, какой блок кода вызывается в любой момент времени. Поэтому я рекомендую вам добавлять журналы, когда загрузка данных начинается, заканчивается и когда вы скрываете представление или показываете представление, чтобы быть уверенным, что все методы вызываются, а также добавлять журналы в жизненные циклы вашей активности.

Другие вопросы по теме