Android асинхронно извлекает данные из БД - PullRequest
0 голосов
/ 27 февраля 2019

Мне нужна безопасная практика для загрузки данных из базы данных.Мне нужно загрузить данные из базы данных Sql и поместить их в список или recylerview.Итак, что я попробовал, я создал класс, который вызывает метод load больше каждый раз, когда пользователь достигает конца списка.И чем это ограничить загрузку данных.Например, «Выбрать * из списка 1, где указан пределItemCount, 20».У меня возникли проблемы с этим, потому что поток, который загружался, запускался 2 раза с одним и тем же значением счетчика.Затем я изменил его, чтобы синхронизировать метод глобального запуска из потока загрузки.И доступ к счетчику из фонового рабочего списка.Это мне очень помогло, и данные были загружены правильно, но у меня все еще были проблемы с этим.Потому что мне нужно вставить данные в просмотр списка из фонового потока, из-за синхронизации и вызова уведомить в основном потоке после.Если я не сделаю это так, у меня все еще будет проблема.

  • Тема A: Начало работы.
  • Тема B: Ожидание завершения потока A (синхронизировано)
  • Поток A: runOnUiThread () пытается заполнить данные.
  • Поток B: разрешено запускать код, получая счет из listView.
  • Поток B: получен такой же счет, как и A,потому что A не закончил оператор вставки.
  • Поток A: Добавлены данные.
  • Поток B: Добавлены те же данные.

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

Этот метод вызывается при достижении конца списка:

private ExecutorService executorService;
    private void loadMore()
    {
        if(!isAdded())
            return;

        if(executorService == null)
            executorService = Executors.newSingleThreadExecutor();

        executorService.execute(new AsyncLoadMoreHashTags(getContext(), this, esaphTagAdapterVertical));
    }

Фоновая тема:

public class AsyncLoadMoreHashTags extends MyDataLoaderClass
{
    private static final Object obLock = new Object();

    public AsyncLoadMoreHashTags(Context context, DataBaseLoadWaiter dataBaseLoadWaiter, SpecialRecylerView spRecylerView)
    {
        super(context, dataBaseLoadWaiter, spRecylerView);
    }

    @Override
    public void run()
    {
        super.run();
        synchronized (AsyncLoadMoreHashTags.obLock)
        {
            List<Object> objectList = null;
            try
            {
                int startFrom = super.getStartFrom()[0];
                SQLHashtags sqlHashtags = new SQLHashtags(super.getSoftReferenceContext().get());

                if(startFrom <= 0)
                {
                    objectList = sqlHashtags.getMostUsedHashtags();
                }
                else
                {
                    objectList = sqlHashtags.getAllHashtagLimited(startFrom);
                }

                sqlHashtags.close();
            }
            catch (Exception ec)
            {
                Log.i(getClass().getName(), "AsyncLoadMoreHashTags run() failed: " + ec);
            }
            finally
            {
                publish(objectList);
            }
        }

    }
}

Что мне нужно, так это просто запустить одну тему за раз.У кого-нибудь есть идея?

Ответы [ 2 ]

0 голосов
/ 27 февраля 2019

Исправлено с этим, работает нормально.

public class AsyncLoadMoreHashTags extends OwnDataLoader
{
    private static AtomicBoolean obLock = new AtomicBoolean(false);

    public AsyncLoadMoreHashTags(Context context, DataBaseLoadWaiter dataBaseLoadWaiter, MomentsRecylerView momentsRecylerView)
    {
        super(context, dataBaseLoadWaiter, momentsRecylerView);
    }

    @Override
    public void run()
    {
        super.run();
        if(!AsyncLoadMoreHashTags.obLock.compareAndSet(false, true)) //when any thread  loading data, its return and skips.
            return;

        List<Object> objectList = null;
        try
        {
            int startFrom = super.getStartFrom()[0];
            SQLHashtags sqlHashtags = new SQLHashtags(super.getSoftReferenceContext().get());

            if(startFrom <= 0)
            {
                objectList = sqlHashtags.getMostUsedHashtags();
            }
            else
            {
                objectList = sqlHashtags.getAllHashtagLimited(startFrom);
            }

            sqlHashtags.close();
            System.out.println("TEST: "  + startFrom + " LOAD: " + objectList.size());
        }
        catch (Exception ec)
        {
            Log.i(getClass().getName(), "AsyncLoadMoreHashTags run() failed: " + ec);
        }
        finally
        {
            publish(objectList, AsyncLoadMoreHashTags.obLock); //Passing the lock object, when data has been added, obLock.set(false); is called.
        }
    }
}
0 голосов
/ 27 февраля 2019

Использование в первую очередь Вам необходимо использовать библиотеку PagedList , предоставленную google , для реализации функции подкачки, и если вы хотите использовать фоновый поток для операции с базой данных вы можете использовать Anko commons для этого.Вот пример,

 internal val pagedList by lazy {
        runBlocking { // Coroutine Context
            withContext(Dispatchers.IO) {
                // Read from database, and it will be initialised in background
            }
        }
    }

, и если вы хотите, чтобы что-то было отправлено в пользовательском интерфейсе , но было выполнено в фоновом режиме Thread, затем перейдите к этому, Операция doAsync , а затем возврат данных в uiThread с помощью пользовательского интерфейса.

 doAsync {
            // LONG OPERATION
            Thread.sleep(2000)

            uiThread {
                callback.onActionsDone(dataList)
            }
        }

Дайте мне знать, если вам нужна дополнительная помощь по этому вопросу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...