0

单击一个按钮,我想从两个 XML 文件创建一个新的 SQLite 数据库。使用 LoaderManager 和 AsyncTaskLoader 似乎适用于此。

Fragment.onCreate() 调用:

setRetainInstance(true);

单击按钮时,我的 Fragment 设置一个正在创建数据库的标志,更改布局以显示 ProgressBar 和取消按钮,并调用:

getLoaderManager().initLoader(0, extra, this);

在我的 PC/Emulator 上操作需要 12 秒。如果我旋转屏幕,加载器会继续调用Fragment的onLoaderProgressUpdate(int)(接口回调方法),完成数据库的创建。但它从不调用 onLoadFinished() 方法,我可以在其中重置布局、启用按钮和需要数据库存在的操作栏菜单。

我尝试在 Fragment.onCreateView() 中执行此操作:

if (mCreatDBInProgress) {
    mBTN_CreateDB.setEnabled(false);
    mDBLayout.setVisibility(View.GONE);
    mProgressBarLayout.setVisibility(View.VISIBLE);
    getLoaderManager().restartLoader(0, null, this);
}

但它调用我的 onCreateLoader() 方法并从头开始整个事情。这是一个问题,因为我没有调用删除数据库的方法并完成确定用于创建数据库的 XML 文件的过程。XML 文件名是我在 Bundle arg 中传递给该方法的文件名。

我不明白为什么 ProgressBar 回调方法继续工作,但 AsyncTaskLoader 不能调用 onLoadFinished() 方法。LogCat 显示它执行了deliverResult()。

我试图使 Bundle 成为成员变量,因此我可以在 restartLoader() 调用中重新使用它。它启动另一个 asyncTaskLoader 并且我的 ProgressBar 在两个线程都尝试更新它时来回移动。最终,它得到一个 SQLConstraintException 试图向数据库中添加已经由第一个线程添加的行。

4

2 回答 2

0

好吧,把我吸到一边!我又想出了一个主意,它奏效了!

而不是restartoader()在旋转后调用,只需调用:

getLoaderManager().initLoader(0, mExtra, this);

出于(无论)原因,这会导致 AsynTaskLoader 仅继续第一个线程(而不是启动另一个线程)并重新链接到我的 Fragment 以进行 onLoadFinished() 调用。

所以:

initLoader() - 如果您使用相同的参数调用它,则将加载器重新连接到您的 Fragment (int, Bundle, this)

于 2013-10-23T23:54:02.243 回答
0

我有同样的问题,当旋转屏幕后 onLoadFinished 没有被调用。我已经看到了很多答案,但没有什么能真正解决这个问题。唯一有帮助的是简单地添加对getLoaderManager()inonCreate方法的调用(由于旋转,在重新创建活动后再次调用它)。它真的为我解决了这个问题:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    LoaderManager loaderMngr = getLoaderManager();
    Log.d(LOG_TAG, "" + loaderMngr);

还有一点关于我为什么不只是放置initLoader或放在restartLoader这里的一点说明:因为在我的情况下,加载程序是在另一个事件发生后触发的,所以这是为我解决这个问题的唯一方法。最初的想法是从这里得到的。

于 2018-06-17T05:59:19.823 回答