屏幕方向更改时未调用加载程序

时间:2012-04-25 18:16:50

标签: android android-asynctask

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

  • 第一个片段是一个edittext和一个提交输入的按钮。
  • 第二个片段显示加载微调器
  • 第三个片段在获取数据时替换加载片段以显示结果。

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"

我没有想法,所以任何帮助都会受到赞赏。

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

您好我可以提出两种可能的解决方案:

1)从你的问题我不完全确定你的表演在AsyncTask中从不调用OnLoadFinished()。我假设是Async数据库调用或Web服务器调用等?

无论onLoadFinished()可能都没有被调用,因为你的Activity在旋转时被销毁了。您需要保存在轮换之前更新的状态并调用onDestroy()

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

所以:

    更新bUpdating = true任务开始时
  • async。即在内 onPreExecute()
  • bUpdating = false完成后。即在内 onPostExecute()

然后当调用onDestroy()时(在屏幕旋转之前始终调用),您可以检查bUpdatingIF TRUE然后您可以将屏幕上已保存在Async任务中的所有详细信息保存到SharePreferences

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

总之,这将是:

  • 将详细信息保存到SharedPreferences 之前屏幕轮换 - onDestroy() - 如果布尔表示异步任务正在运行。
  • onResume() AFTER 屏幕轮换检查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");
    }
}

取自此post

的示例

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

还有一个link to SharePreferences,你没有在

之前使用它

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