片段setRetainInstance(true)保存View属性

bco*_*rso 2 android android-fragments android-view

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

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

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

进一步来说:

  1. 如果setRetainInstanceStatetrue,以上代码是View在定向调用之间保留状态的最佳方法吗?
  2. 如果我不与后台任务交互,是否应该仅使用setRetainInstanceState(false)和使用Bundle来维护View状态?(注意:如果使用捆绑包,则无法使用setRetainInstance == true

Mar*_*lho 5

setRetainInstance不要让你在内存视图只保留相同的实例作为一种Singleton基于tag或者ID,你给你的片段。很好,因为当您Fragment进入后台时,您的视图将被破坏,而不是不必要的内存。

回答您的两个问题:

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

  2. 不,一旦您将其设置为Fragment,Android操作系统将为相同的标签或ID保留相同的实例,因此在进入后台时,请记住将Bundlewith视图状态保存onSaveInstanceState为下一次恢复视图状态。

在此处阅读有关Fragments生命周期的更多信息:http : //developer.android.com/guide/components/fragments.html#Lifecycle

有关的onSaveInstanceState更多信息,请参见:http : //developer.android.com/reference/android/app/Fragment.html#onSaveInstanceState(android.os.Bundle)

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

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...
    }
}
Run Code Online (Sandbox Code Playgroud)

更改您的fragment状态changeStateTo