标签: onsaveinstancestate

在提交FragmentTransaction之前检查状态是否已保存

我有时会看到以下用于提交的堆栈跟踪,当用户没有查看活动时(状态保存后)可能会发生这种情况:

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
    at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1327)
    at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1338)
    at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595)
    at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:574)
Run Code Online (Sandbox Code Playgroud)

看看Android源代码,这很有意义:

private void checkStateLoss() {
        if (mStateSaved) {
            throw new IllegalStateException(
                    "Can not perform this action after onSaveInstanceState");
        }
        if (mNoTransactionsBecause != null) {
            throw new IllegalStateException(
                    "Can not perform this action inside of " + mNoTransactionsBecause);
        }
 }
Run Code Online (Sandbox Code Playgroud)

现在,我想知道是否有任何方法(除了在(保存/恢复)InstanceState中存储类变量)以检查片段是否将以不合需要的状态提交,这样我可以存储事务以供日后使用在适当的时候提交.

android android-fragments fragmentmanager android-savedstate onsaveinstancestate

41
推荐指数
3
解决办法
2万
查看次数

什么时候onRestoreInstanceState调用?

对不起我的不解,但我是android开发的新手.

我有一个活动A和活动B的应用程序,我从活动A转到活动B.当我离开活动A时,onSaveInstanceState方法被调用,但是当我回到活动A时(来自活动B在同一个应用程序中) ),onCreate方法中的bundle 为null.

我该怎么办,以保存活动A以前的状态?我只想存储应用程序生命周期的数据.

有人可以帮我弄这个吗?

这是我的活动A的代码:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    if (savedInstanceState != null)
    {
        Log.v("Main", savedInstanceState.getString("test"));
    }
    else
    {
        Log.v("Main", "old instance");
    }
}  

@Override
public void onSaveInstanceState(Bundle savedInstanceState) 
{
    Log.v("Main", "save instance");

    savedInstanceState.putString("test", "my test string");

    super.onSaveInstanceState(savedInstanceState);
}


public void buttonClick(View view)
{
    Intent intent = new Intent(this, Activity2.class);
    startActivity(intent);
}
Run Code Online (Sandbox Code Playgroud)

这是我的活动B的代码,当我按下按钮返回活动A:

public void onBack(View view)
{
    NavUtils.navigateUpFromSameTask(this);
}
Run Code Online (Sandbox Code Playgroud)

android android-lifecycle onrestoreinstancestate onsaveinstancestate

38
推荐指数
2
解决办法
4万
查看次数

android:support:fragments 保存的 Activity 越来越大导致 TransactionTooLargeException

我有一个控制多个片段的活动。默认片段是HomepageFragment. 当替换到不同的 Fragment 时,我总是确保堆栈保持平坦 - 这意味着只有HomepageFragment保持在堆栈中并在其顶部是当前 Fragment。例如:

  1. 活动开始于 HomepageFragment
  2. FragmentA需要替换 to - 一切都是好的原因HomepageFragment是最后一个 Fragment
  3. 现在堆栈是HomepageFragment->FragmentA
  4. FragmentB需要替换为- 首先弹出堆栈上的最后一个 Fragment ( fragmentA) 然后替换为FragmentB
  5. 现在堆栈是HomepageFragment->FragmentB

在生产中,我看到很多TransactionTooLargeException崩溃。

我曾经TooLargeTool跟踪问题的来源,我发现当我在活动中的片段之间切换时,其中有一个android:support:fragmentsSaveInstanceState变得越来越大(呈指数级),直到发生崩溃。

似乎即使从堆栈中弹出时,有关原始事务的一些数据也会继续保存。

按照此处的建议将其删除会导致 Activity 在被操作系统杀死后无法正确恢复。

我压平堆栈的方法有什么问题吗?有没有更好的方法?究竟保存在什么数据下android:support:fragments

注意:我没有为这些片段设置任何参数。此外,它们在其 saveInstanceState 包中保存了非常小的数据。

谢谢!

android android-fragments android-activity onsaveinstancestate transactiontoolargeexception

11
推荐指数
1
解决办法
886
查看次数

从bottomNavigationView导航到片段B时保存片段A的状态

我是 Android 新手,一段时间以来我一直在努力保存片段的状态。我的应用程序在底部导航视图中有 5 个选项(我使用的是 Android 的默认 Activity)。在片段 A(实际上称为“SearchFragment”)中,我有一个按钮,单击时它会在文本框中设置一些文本。我想在导航到另一个片段并返回到片段 A 时保存该片段的状态(其中包含文本)(并且上一个按钮单击时的文本仍然存在)。

例如,根据我编写的代码,它会在更改方向时保存片段的状态,但在导航到其他片段然后返回时不会这样做。

我怎样才能更改代码?或者是否有其他方法可以保存导航时片段的当前状态?我真的需要一些帮助......感谢您的关注!

我的 mainActivity 如下所示:

    public class MainActivity extends AppCompatActivity {

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            BottomNavigationView navView = findViewById(R.id.nav_view);
            // Passing each menu ID as a set of Ids because each
            // menu should be considered as top level destinations.

            AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
                    R.id.navigation_search, R.id.navigation_explore, R.id.navigation_trips, R.id.navigation_groups,R.id.navigation_profile)
                    .build();

            NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
            NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
            NavigationUI.setupWithNavController(navView, navController);
        }

    }
Run Code Online (Sandbox Code Playgroud)

片段类如下所示:


    public …
Run Code Online (Sandbox Code Playgroud)

android uinavigationbar android-fragments onsaveinstancestate bottomnavigationview

8
推荐指数
1
解决办法
1万
查看次数

android - 对多个活动使用相同的片段

我想在多个活动中使用一个片段。在我将在第一个活动中使用它,我创建了它

    final ScoreBoard fragment = new ScoreBoard();
    getFragmentManager()
            .beginTransaction()
            .add(R.id.fragment_container, fragment)
            .commit();
Run Code Online (Sandbox Code Playgroud)

在第二个活动中,我在 onCreate() 方法中放置了相同的代码。但是,即使我已经通过 onSavedInstanceState() 和 onActivityCreated() 保存了它们,片段也会不断重置并且不会将其值保留在第二个活动中。我是在重新创建片段并重置它吗?谢谢你。

android-fragments android-activity android-fragmentactivity onactivityresult onsaveinstancestate

6
推荐指数
1
解决办法
3777
查看次数

恢复具有两个具有相同ID的视图的片段

我有一个复杂的布局来实现.它有19个部分可以根据用户先前输入的大量参数显示或不显示.为了简化代码并且不显示未使用的部分,动态创建布局.

一切都在碎片里面.片段有一个用作容器的LinearLayout,当创建片段时,我生成所有必要的部分.

每个部分由其自己的本地适配器管理,该适配器负责扩展此部分的布局并将其添加到容器中.

一切都很好.问题是2个部分具有完全相同的结构,因此它们共享相同的xml布局.因此,两个部分的内部视图具有相同的ID.这不是问题,因为该部分在其适配器中本地管理.当我转到下一个片段然后再回到这个片段时,会出现问题.系统尝试恢复视图的先前状态,并且由于这两个部分具有相同的ID,因此在恢复第二部分时,其值也将设置为第一部分.

是否有任何解决方案来管理它或告诉片段不恢复其状态(因为无论如何都要手动重新加载).

这是当前结构的一个很好的例子:

片段xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>
Run Code Online (Sandbox Code Playgroud)

部分xml

<EditText xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/section_text"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>
Run Code Online (Sandbox Code Playgroud)

片段代码

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_layout, container, false);

    if (<condition>)
       createSection1(getContext(),view);

    if (<condition>)        
       createSection2(getContext(),view);

    return view;
}


private void createSection1(Context context, ViewGroup root){
    Section1Adapter adapter = new Section1Adapter(context, root);
    // ...
}

private void createSection2(Context context, ViewGroup root){
    Section2Adapter adapter = new Section2Adapter(context, root);
    // ... …
Run Code Online (Sandbox Code Playgroud)

android android-fragments onsaveinstancestate

6
推荐指数
1
解决办法
399
查看次数

在onSaveInstanceState显示后无法执行此操作

我收到以下崩溃报告:

致命异常:java.lang.IllegalStateException:无法在android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager)的android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1832)的onSaveInstanceState之后执行此操作. java:1850)在android.support.v4.app.BackStackRecord.com发布内部(BackStackRecord.java:643)android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:603)android.support.v4.app .DialogFragment.show(DialogFragment.java:143)

以下代码导致崩溃,为了清楚起见,我删除了一些简单的设置代码.我已经阅读了这个错误,据我所知,.show()在用户交互中应该是安全的onClick().我唯一能想到的是,这query()需要花费很长时间才能完成用户的交换.这是对这个错误的合理解释吗?即使使用大型数据库,它也会立即在我的设备上运行.还有其他可能吗?谢谢!

    foldersButton.setOnClickListener(new View.OnClickListener()
    {
        @Override
        public void onClick(View v)
        {
            final List<String> paths = new ArrayList<>();

            try(Cursor c = getActivity().getContentResolver().query(Meta.CONTENT_URI,
                    new String[]{"DISTINCT " + Meta.PARENT}, null, null,
                    Meta.PARENT + " ASC"))
            {
                while (c != null && c.moveToNext())
                {
                    String path = c.getString(c.getColumnIndex(Meta.PARENT));

                    // We place the excluded folders at the end
                    if (!mExcludedFolders.contains(path))
                        paths.add(path);
                }
            }

            [setup...]

            int[] position = new int[2];
            foldersButton.getLocationOnScreen(position);
            FolderDialog dialog = FolderDialog.newInstance(
                    paths.toArray(new String[paths.size()]), …
Run Code Online (Sandbox Code Playgroud)

android android-fragments android-dialogfragment onsaveinstancestate

5
推荐指数
2
解决办法
8260
查看次数

onSaveInstanceState 在 onDestroyView 之后调用

我在这里处理奇怪的片段生命周期行为。

我有一个托管两个片段的活动:CityFragment - 显示城市列表和 WeatherFragment - 显示所选城市的天气预报。

当应用程序启动时,CityFragment 将显示在屏幕上,当用户选择城市时 - WeatherFragment 通过 supportFragmentManager 和 backstack 添加。然后,如果用户想要旋转屏幕,我会得到图片上的情况在此输入图像描述

  • 0-2 -- CitiesFragment 启动
  • 3-7 -- 用户选择城市,WeatherFragment 显示在屏幕上
  • 8-18 -- 屏幕旋转

正如您在日志中看到的,用户选择城市后,CitiesFragment 会调用 onStop 和 onDestroyView,之后的片段视图为 null。但是当屏幕旋转时,CitiesFragment onSaveInstanceState 会被调用(当视图已经被销毁时)。

这里的问题是,将代码转换为 kotlin 并使用合成进行视图访问后,当我想保存 recyclerview 第一个可见元素以在之后恢复时,我在 onSaveInstanceState 中收到 NullPointerException

val firstVisiblePosition = (recycler_view_cities.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
Run Code Online (Sandbox Code Playgroud)

使用旧的 java 实现,它工作得很好,因为我将 recycler_view_cities 的引用存储在片段中,并且可以在那里访问它。

  • 问题 1. CitiesFragment 的 onSaveInstance 状态不应该在 onStop 和 onDestroyView 之前调用吗?
  • 问题2.遇到这种情况如何处理?

android android-fragments kotlin-android-extensions onsaveinstancestate

5
推荐指数
1
解决办法
1971
查看次数

此捆绑包中的“androidx.lifecycle.BundlableSavedStateRegistry.key”是什么?

我正在toolargetool调查应用程序崩溃的原因TransactionTooLargeException

androidx.lifecycle.BundlableSavedStateRegistry.key当我将应用程序置于后台时,我看到这个密钥大约有 400 KB。

这个密钥是什么以及它从哪里来?我怎样才能减少包中这个的大小?

android kotlin android-bundle onsaveinstancestate androidx

5
推荐指数
1
解决办法
2145
查看次数

onRequestPermissionsResult()中的Android java.lang.IllegalStateException

我正在使用SD卡,所以试图在运行时获得许可.这是代码:

public class MainActivity extends AppCompatActivity implements FileListFragment.OnFragmentInteractionListener {

private static final int MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE = 111;

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE);
        }

         ...................
         ................
    }

@Override
    public void onRequestPermissionsResult(int requestCode,
                                           String permissions[], int[] grantResults) {
        switch (requestCode) {
            case MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE: {
                // If request is cancelled, the result arrays are empty.
                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                    FileListFragment fileListFragment = FileListFragment.newInstance(0);  // **Error line** …
Run Code Online (Sandbox Code Playgroud)

permissions android illegalstateexception onsaveinstancestate

3
推荐指数
1
解决办法
2812
查看次数

发送失败结果ResultInfo | java.lang.IllegalStateException:无法在onSaveInstanceState之后执行此操作

我有简单的应用程序首先我显示MainActivity然后MainActivity变得可见我显示TransparentActivity之后onClick我杀了TransparentActivity我创建并显示对话框.在上一步中我得到错误

错误

Failure delivering result ResultInfo{who=null, request=1234, result=-1, data=Intent {  }} to activity {com.example.kylu.layout/com.example.kylu.layout.GuidePhotoAlbum}: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
Run Code Online (Sandbox Code Playgroud)

主要活动

public class MainActivity extends FragmentActivity
{
public static boolean flag=false;
    private static int REQUEST_CODE = 1234;

    @Override public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.mylayout);
    }

@Override
protected void onResume() {
    super.onResume();
    //transparentShows only once
    if(!flag)
    {
        Intent i = new Intent(this, TransparentTip.class);
        startActivityForResult(i, REQUEST_CODE);
        flag=true;
    }
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        if (REQUEST_CODE == …
Run Code Online (Sandbox Code Playgroud)

android dialog onresume android-lifecycle onsaveinstancestate

3
推荐指数
1
解决办法
723
查看次数

如何检查 onSaveInstanceState 中 Bundle 对象的大小?

我正在使用 Android Studio 3.0.1,它允许检查Bundle对象onSaveInstanceState

@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
}
Run Code Online (Sandbox Code Playgroud)

为此添加一个断点,一旦调试器停止,右键单击Bundle屏幕截图中所示的对象,然后从上下文菜单中选择“显示捆绑对象...”。

Android Studio - 显示捆绑对象

然后会打开一个窗口以列出Bundle对象,如下面的屏幕截图所示:

Android Studio - 捆绑对象

有没有办法找出整个和它的孩子们占据了多少内存Bundle?我想确定更大的块来优化并避免TransactionTooLargeException在 Android >= 7 上抛出。

像 Ubuntu磁盘使用分析器这样的东西会有所帮助 - 请参阅 screeshot:

磁盘使用分析器

android android-studio android-bundle onsaveinstancestate

3
推荐指数
1
解决办法
2254
查看次数

IllegalStateException onSaveInstanceState 显示 DialogFragment 后无法执行此操作

这是我第一次遇到这个问题。

我已经仔细研究了 SO 上的几个答案,尤其是这个这个,但它没有解决我的问题,并且大多数答案不能用作解决我的案例的安全可靠的方法。

我已经尝试过:

  • 覆盖onSaveInstanceState并且不调用 super

但 commitAllowingStateLoss 不能用于第一种情况。

我正在寻找有关如何避免引发此异常以及如何实现引发异常的操作的解释(在第一种情况下,显示dialogFragment)。我已经知道如何引发此异常,但是,我不知道在我的情况下引发了什么。它在我的应用程序中出现两次:

第一个发生在一个非常简单的活动中,我有一个简单的动画,在该动画的末尾我显示了一个 DialogFragment (SplashActivity):

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    val potentialLanguage = storage.getString(Constants.LANGUAGE)
    val lang = if (potentialLanguage.isNotEmpty()) {
        potentialLanguage
    } else {
        Locale.getDefault().language
    }
    val language = Language.getFromName(lang)!!
    val dm = res.displayMetrics
    val conf = res.configuration
    conf.setLocale(Locale(language))
    saveLanguage(context, lang)
    // Use conf.locale = new Locale(...) if targeting lower versions
    res.updateConfiguration(conf, dm)
    initWarningDialog()
    RevelyGradient
        .radial()
        .colors(
            intArrayOf(
                getColor(R.color.backgroundOnBoardingStart),
                getColor(R.color.backgroundOnBoardingEnd)
            )
        )
        .onBackgroundOf(root)
    ivCap.animate() …
Run Code Online (Sandbox Code Playgroud)

android android-lifecycle onsaveinstancestate

3
推荐指数
1
解决办法
1万
查看次数