片段setRetainInstance(true)保存View属性 [英] Fragment setRetainInstance(true) save View properties

查看:151
本文介绍了片段setRetainInstance(true)保存View属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对保存保存在Android片段内部的View状态的最佳做法感到困惑.

I'm confused about the best practice for saving the states of Views that live inside of fragments in Android.

我认为setRetainInstance(true)可以解决问题;但是,尽管这确实保留了在Fragment中声明的旧的全局View引用,但在扩展布局时将不会使用这些视图.因此,我必须手动将属性从旧的全局View引用转移到膨胀布局中的新View.请参阅下面的代码,了解我的操作方式.

I thought that setRetainInstance(true) would do the trick; however, while this does retain the old global View references declared in the Fragment, those Views will not be used when inflating the layout. Thus, I have to manually transfer the properties from the old global View references to the new Views in the inflated layout. See the code below for how I'm doing this.

public static class MyFragment extends Fragment {

    // I need to save the state of two views in the fragment
    ProgressBar mProgress;
    TextView mText;


    @Override public void onCreate(Bundle savedInstanceState) {
        // savedInstanceState == null if setRetainInstance == true
        super.onCreate(savedInstanceState);

        // Retain the instance between configuration changes
        setRetainInstance(true);
    }

    @Override public View onCreateView(LayoutInflater i, ViewGroup c, Bundle b) {
        // Inflate xml layout for fragement (orientation dependent)
        View v = i.inflate(R.layout.fragment_main, c, false);

        // Grab Views from layout
        ProgressBar tmpProgress = (ProgressBar) v.findViewById(R.id.progress);
        TextView tmpText        = (TextView) v.findViewById(R.id.text);

        // If View References exist, transfer state from previous Views
        if(mProgress != null){ 
            tmpProgress.setProgress(mProgress.getProgress());
            tmpText.setText(mText.getText());
        }

        // Replace View references
        mProgress = tmpProgress;
        mText     = tmpText;
        return v;
    }
}

我觉得setRetainInstanceState(true)应该主要用于使片段保持活动状态,以便后台进程可以与其保持连接.如果是这种情况,我是否不应该使用此方法来保留View s的状态?

It's my feeling that setRetainInstanceState(true) should mainly be used for keeping a fragment alive so that background processes can maintain a connection to it. If that's the case should I not be using this method to retain the states of my Views?

更具体地说:

  1. 如果setRetainInstanceStatetrue,以上代码是在定向调用之间保留View状态的最佳方法吗?
  2. 如果我不与后台任务交互,是否应该只使用setRetainInstanceState(false)并使用Bundle来维护View状态? (注意:如果setRetainInstance == true不能使用捆绑包)
  1. if setRetainInstanceState is true, is the above code the best way to retain the View states between orientation calls?
  2. If I'm not interacting with background tasks, should I just use setRetainInstanceState(false) and use Bundles to maintain the View states? (Note: bundles cannot be used if setRetainInstance == true)

推荐答案

使用setRetainInstance请勿将视图保留在内存中,而只将与您基于tagIDSingleton实例相同给你的片段.很好,因为当您Fragment进入后台时,您的视图将被破坏,而不是不必要的内存.

Use setRetainInstance DO NOT keep your view in memory just keep same instance as a kind of Singleton based on tag or ID that you give to your fragment. It's good because when you Fragment goes to background your view is destroyed and not unecessary memory.

回答两个问题:

  1. 不要保留您的视图!每次调用onCreateView时都要重新创建视图.为了保持状态和更多状态,请使用全局变量.

  1. Do not keep your view created! Recreate your view every time onCreateView is called. To keep states and more use global variables.

否,一旦您将其设置为Fragment,Android OS将为相同的标签或ID保留相同的实例,因此当进入后台时,请记住以onSaveInstanceState的视图状态保存您的Bundle以便下次恢复视图状态.

No, once you set it your Fragment, Android OS will keep same instance for same tag or ID so when it goes to background keep in mind to save your Bundle with view state at onSaveInstanceState to recover view status at next time.

在此处详细了解有关片段生命周期的信息: http://developer.android.com/guide/components/fragments.html#Lifecycle

Read more about Fragments lifecycle here: http://developer.android.com/guide/components/fragments.html#Lifecycle

关于onSaveInstanceState的更多信息,请参见:

And about onSaveInstanceState, see more here: http://developer.android.com/reference/android/app/Fragment.html#onSaveInstanceState(android.os.Bundle)

例如,您可以执行以下操作:

For example you could do something like that:

package com.example.stackoverflowsandbox;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class MyFragment extends Fragment {
    public static String VIEW_STATE_A = "a";
    public static String VIEW_STATE_B = "b";
    public static String VIEW_STATE_C = "c";

    private String       currentState = MyFragment.VIEW_STATE_A;
    private View         view;

    public void changeStateTo( final String newState ) {
        if ( this.currentState != newState ) {
            this.currentState = newState;

            this.updateViewState( this.currentState );
        }
    }

    @Override
    public View onCreateView( final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState ) {
        this.setRetainInstance( true );

        this.view = inflater.inflate( R.layout.my_view, null );

        this.updateViewState( this.currentState );

        return this.view;
    }

    @Override
    public void onDestroyView() {
        this.view = null; // release the reference to GC

        super.onDestroyView();
    }

    private void updateViewState( final String state ) {
        // do what you want to do with your view here...
    }
}

通过changeStateTo更改fragment状态.

这篇关于片段setRetainInstance(true)保存View属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆