Android从数据库异步获取数据

标签 android mysql multithreading fetch

我需要一种安全的做法来从数据库加载数据。 我需要从 Sql 数据库加载数据并将其放入列表或 recylerview 中。 所以我尝试了,我创建了一个类,每次当用户到达列表末尾时,它都会调用方法加载更多。而且它加载的数据有限。 就像“选择 * 从其中 1 限制 listItemCount,20”。 我遇到了这个问题,因为正在加载的线程以相同的计数值启动了两次。我已经将其更改为从加载线程同步全局运行方法。并从列表的后台工作人员访问计数。这对我帮助很大,并且数据已正确加载,但我仍然遇到问题。因为我需要从后台线程将数据插入listview,因为之后在主线程中进行同步和调用notify。如果我不这样做,我仍然会遇到问题。

  • 线程 A:开始工作。
  • 线程 B:WAITING完成线程 A(已同步)
  • 线程 A:runOnUiThread() 尝试填充数据。
  • 线程 B:允许运行代码,从 listView 获取计数。
  • 线程 B:获得与 A 相同的计数,因为 A 未完成插入 声明。
  • 话题 A:已添加数据。
  • 线程 B:添加了相同的数据。

在此之后,我添加了一个atomicboolean,如果线程正在运行,他就不会被执行。这样它就可以完美工作,但有时您必须向上和向下滚动一点才能触发更多负载。 我认为这个解决方案对我来说有点脏。现在有人如何根据 ListView 的列表大小在后台线程中加载数据而不出现此问题?

到达列表末尾时调用此方法:

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);
            }
        }

    }
}

我需要的是,一次只启动一个线程。 有人有想法吗?

最佳答案

首先使用你应该使用 PagedList google提供的库,用于实现分页功能,如果您想使用后台线程进行数据库操作,可以使用Anko common 来执行此操作。这是一个例子,

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

如果您想要在 UI 上调度在后台执行线程中执行某些操作,则执行此 doAsync 操作,然后返回使用自定义接口(interface)在 uiThread 中获取数据。

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

            uiThread {
                callback.onActionsDone(dataList)
            }
        }

如果您需要更多帮助,请告诉我。

关于Android从数据库异步获取数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54902501/

相关文章:

android - 在 Android 的 OKhttp 中通过 POST 请求发送 JSON 正文

android - 如何使用Android webview下载一个文本文件

php - 使用 2 个文本字段将多个图像上传到数据库

java - DeferedResult 和 CompletableFuture 之间的区别

android - 通讯录收藏夹搜索栏

Android FusedLocationProviderApi : Incoming intent has no LocationResult or LocationAvailability

mysql - 如何查看程序发送到本地mySQL数据库的本地流量?

MySQL 按子选择结果排序

c++ - 如何在不触及函数本身的情况下暂停和恢复 C++11 std::thread 的函数?

java - 像 read() 这样的 I/O 方法如何在 Java 中将线程置于阻塞状态?