Android从db

时间:2019-02-27 09:51:45

标签: android mysql multithreading fetch

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

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

在此之后,我添加了atomicboolean,如果线程正在运行,则不会执行该操作。有了它,它可以完美地工作,但是有时您必须向上或向下滚动以触发更多负载。 我认为这种解决方案对我来说有点脏。现在有人在后台线程中如何根据列表视图的列表大小分段加载数据吗?

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

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 :(得分:0)

首先使用您必须使用 google 提供的PagedList库来实现分页功能,并且如果要使用后台线程 数据库操作,您可以使用Anko 常见 来执行此操作。这是一个例子,

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

如果您希望在用户界面上分派某些东西但在后台线程中执行,请执行此操作, doAsync ,然后返回使用自定义界面在 uiThread 中添加数据。

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

            uiThread {
                callback.onActionsDone(dataList)
            }
        }

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

答案 1 :(得分:0)

像这样修复它,可以正常工作。

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.
        }
    }
}
相关问题