8

我在使用时遇到了一些麻烦AsyncTaskLoader,屏幕方向发生了变化。让我给你一些关于我的应用程序结构的背景信息:我有一个非常简单的应用程序,它从 url 获取结果并显示它。该应用程序由一个FragmentActivity和三个组成Fragments。我的三个片段如下:

  • 第一个片段是一个编辑文本和一个提交输入的按钮。
  • 第二个片段显示了一个加载微调器
  • 当获取数据以显示结果时,第三个片段替换加载片段。

用于从AsyncTaskLoader内容提供者(如果已缓存)或网络加载数据。

一切都很好,直到屏幕改变!我查看了的输出,LoaderManager.enableDebugLogging(true) 似乎问题的根源是LoaderCallbacks.onLoadFinished在我的活动中没有被调用。

这是启动加载程序的一段代码:

/* This function is defined in the "first" fragment in an interface and
 * implemented in the activity */ 
@Override
public void onFormSubmission(String word) {                     

    showLoadingFragment();

    if ( mWord == null || mWord.equals(word) ) {
        getSupportLoaderManager().initLoader(0, word, this);
    } else {
        getSupportLoaderManager().restartLoader(0, word, this);
    }

    // Store the word
    mWord = word;
}

显示结果的代码:

@Override
public void onLoadFinished(Loader<Bundle> loader, Bundle data) {
    // Validation and other stuff

      ResultFragment fragment = new ResultFragment();

      // Add the fragment to the 'result_fragment_container' FrameLayout
      getSupportFragmentManager()
            .beginTransaction()
            .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
            .setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out)
            // Replace loading fragment with the result
            .replace(R.id.result_fragment_container, fragment)
            .commitAllowingStateLoss(); 
}

我尝试但失败的方法:

  • 设置setRetaininstance(true)在片段中。
  • android:configChanges="orientation|keyboardHidden|keyboard"在清单中设置。

我没有想法,所以任何帮助将不胜感激。

4

2 回答 2

1

嗨,我可以建议 2 种可能的解决方案:

1)从您的问题来看,我不完全确定您执行的进程从不在 AsyncTask 中调用 OnLoadFinished()。我假设是Async数据库调用或 Web 服务器调用等?

不管 onLoadFinished() 可能不会被调用,因为您的 Activity 在旋转时被销毁。您需要保存您在轮换之前更新的状态并onDestroy()调用

您可以尝试保留类变量状态标志。这是在您的“更新”Async任务中设置的,它标记您的Async任务是否仍在运行,即“更新”与否。

所以:

  • bUpdating = true当您的更新async任务开始时。即内 onPreExecute()
  • bUpdating = false当它完成时。即内 onPostExecute()

然后什么时候 onDestroy()被调用(总是在屏幕旋转之前调用)你可以检查bUpdating. IF TRUE然后您可以将所有已保存在Async任务中的详细信息保存在屏幕上,以SharePreferences

检查onResume()您的特定SharePreferences变量,如果它们存在,则Async再次启动更新。

所以简而言之,这将:

  • 将详细信息保存到屏幕旋转SharedPreferences 之前onDestroy()- - 如果布尔值表示异步任务正在运行。
  • onResume() 屏幕旋转SharedPreferences检查并通过保存详细信息Async
  • 在此之后,您应该保证您的onLoadFinished()方法被调用。

可能还有一种更可靠的方法来检查屏幕旋转,我没有做太多。

2)当然,另一种选择是在您的特定活动上完全阻止屏幕旋转(因为真的,您需要在该屏幕上旋转吗?)。

我有一个在后台录制视频并上传 10 秒片段的应用程序。它给屏幕旋转和我的异步任务带来了很大的麻烦,所以我完全阻止了旋转,因为它完全没有必要。这是 AndroidManifest.xml 文件将屏幕方向锁定为纵向的代码:

     <activity 
        android:name="com.blah.YourActivity"
        android:label="Register"
        android:screenOrientation="portrait">
    </activity>

我希望这可以帮助你

编辑:另外,知道屏幕正在旋转可能是更好的更明确的方法:

即这种代码:

public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);

    if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
        Log.e(TAG, "ORIENTATION_LANDSCAPE");
    } else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
        Log.e(TAG, "ORIENTATION_PORTRAIT");
    }
}

取自这篇文章的示例

你可以把你的SharePreferences存档放在那里。但 onResume() 仍将用于从中获取您的详细信息。

还有一个链接,SharePreferences以防您以前没有使用过它

Edit2!:另一件事。我刚刚重新阅读了您的问题,您出于某种原因提到了“加载器”,我想到了这是在保存数据,而不是加载。AsyncTaskLoader()您是否尝试过在调用onResume() 时简单地重新调用?如果您不保存,那么您可以忽略我所说的关于保留数据的所有内容,SharePreferences因为您可以在 onResume() (在 Rotation 之后运行)再次启动加载异步任务

于 2013-03-06T02:21:32.647 回答
1

你应该getSupportLoaderManager().initLoader(0, null, this);输入onActivityCreated 方法。如果加载器已经存在,initLoader 将创建或重新连接加载器

于 2013-03-05T23:55:42.400 回答