如果用户导航到另一个片段,则从一个片段和对话框保存信息

时间:2014-10-02 00:26:45

标签: android android-activity android-fragments android-bundle

我有一个屏幕,用户按下按钮以显示DialogFragment EditText。他们输入信息,然后按Ok。如果他们再次按下按钮,我就会这样做,EditText将显示他们刚刚放入的信息,一切正常。

但是,如果他们输入信息,请按Ok,然后使用选项菜单查看另一个屏幕/ fragment,该信息将不会显示在EditText中一旦他们再次按下按钮。

即使用户暂时离开该屏幕,我如何保存信息?我认为在片段类中需要newInstance方法,然后让托管活动调用newInstance而不是构造函数。但我不确定如何实现它。任何帮助赞赏。谢谢!

SingleFragmentActivity

public abstract class SingleFragmentActivity extends FragmentActivity
{
    protected abstract Fragment createFragment();

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

        FragmentManager fm = getSupportFragmentManager();
        Fragment fragment = fm.findFragmentById(R.id.fragmentContainer);

        if (fragment == null)
        {
            fragment = createFragment();
            fm.beginTransaction()
                .add(R.id.fragmentContainer, fragment)
                .commit();
        }
    }
}

来自托管活动的相关代码,AdviceActivity:

public class AdviceActivity extends SingleFragmentActivity
{
    @Override
    protected Fragment createFragment()
    {
        return new AdviceFragment();
    }
}

来自托管片段的相关代码,AdviceFragment:

private boolean isTextButtonFirstClick = true;

...

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState)
{
    mTextButton = (Button) v.findViewById(R.id.textButton);
    mTextButton.setOnClickListener(new View.OnClickListener()
    {
        public void onClick(View v)
        {
            if (isTextButtonFirstClick)
            {
                FragmentManager fm = getActivity().getSupportFragmentManager();
                InputTextFragment dialog = InputTextFragment.newInstance("", isTextButtonFirstClick);
                dialog.setTargetFragment(AdviceFragment.this, REQUEST_TEXT);
                dialog.show(fm, DIALOG_TEXT);
                isTextButtonFirstClick = false;
            }
            else
            {
                FragmentManager fm = getActivity().getSupportFragmentManager();
                InputTextFragment dialog = InputTextFragment.newInstance(mAdvice.getText(), isTextButtonFirstClick);
                dialog.setTargetFragment(AdviceFragment.this, REQUEST_TEXT);
                dialog.show(fm, DIALOG_TEXT);
            }
        }
    });
...
}

DialogFragment InputTextFragment的相关代码:

public static InputTextFragment newInstance(String text, boolean isTextButtonFirstClick)
{
    Bundle args = new Bundle();
    args.putSerializable(EXTRA_TEXTBUTTON_FIRSTCLICK, isTextButtonFirstClick);
    args.putSerializable(EXTRA_TEXT, text);

    InputTextFragment fragment = new InputTextFragment();
    fragment.setArguments(args);

    return fragment;
}

...

@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
    ...

    boolean isTextButtonFirstClick = getArguments().getBoolean(EXTRA_TEXTBUTTON_FIRSTCLICK);

    final EditText editText = (EditText) v.findViewById(R.id.dialogInputEditText);
    if (!isTextButtonFirstClick)
    {
        editText.setText(text);
        editText.setSelection(text.length());
    }

    ...
}

XML activity_fragment:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/fragmentContainer"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

</RelativeLayout>

1 个答案:

答案 0 :(得分:1)

听起来好像布尔值isTextButtonFirstClick被错误地设置为false。

这将理解在导航过程中创建的Advice Fragment的新实例。

尝试

  • 在建议片段的onCreate中设置setRetainInstance(true)以保持布尔值。

  • 如果R.id.fragmentContainer是XML中的片段标记,则将其更改为LinearLayout或RelativeLayout(无论如何都要在顶部添加片段,我怀疑findFragmentById始终返回null)

  • 将您的活动中的代码更改为:

    FragmentManager fm = getSupportFragmentManager();
    Fragment fragment = fm.findFragmentByTag("singleFragment");
    
    if (fragment == null)
    {
        fragment = createFragment();
    }
    
       fm.beginTransaction()
            .replace(R.id.fragmentContainer, fragment,  "singleFragment" )
            .commit();
    

通常在以编程方式添加片段时,您使用标签,而在使用XML定义片段时,让Android框架处理生命周期,您可以通过id找到它。

在我看来,好像你处于中间解决方案中,试图同时做这两种解决方案,这将无法按预期工作。

如果存在格式问题,希望这可以提前帮助和抱歉。答案是用手机写的:-)

修改

如果您只想保存简单类型的信息(例如布尔值),我会在此向您指出我的旧答案之一:Saving textview in a fragment when rotating screen

您的上一条评论显示您有一些您想要保留的复杂信息(文字,照片,视频等)。

让所有Parcelable成为一个巨大的痛苦,所以这是我的第二个建议:

  1. 将EventBus添加到您的项目https://github.com/greenrobot/EventBus
  2. 为信息创建一个持有者类,例如

    public class AdviceHolder {
        private boolean isTextButtonFirstClick;
        private String text;
        private BitMap image;
        ... 
    
       // setter and getter methods (if using eclipse alt+shit+s 'create setter and getters from fields') 
    }
    
  3. 现在,在启动AdviceActivity时,您需要准备一个新的AdviceHolder

    public class AdviceActivity extends SingleFragmentActivity
    {
        @Override
        public void onCreate(Bundle savedInstanceState) {
            // make a new AdviceHolder if none existed
            AdviceHolder holder = new AdviceHolder();
            AdviceHolder existingHolder = EventBus.getDefault().getStickyEvent(AdviceHolder.class);
            if (existingHolder == null) {        
                 EventBus.getDefault().postSticky(holder);
            }
    
            super.onCreate(savedInstanceState);
        }
    
        @Override
        protected Fragment createFragment()
        {
            return new AdviceFragment();
        }
    }
    
  4. 此步骤将使代码中的AdviceHolder对象随时随地。将其视为全球存储库。

    这意味着无论您如何在Activites或Fragments之间移动,他们都可以访问AdviceHolder并进行编辑。

    例如,你在AdviceFragment:

    private AdviceHolder holder;
    
    ...
    @Override
    public void onCreate (Bundle savedInstanceState) {
        AdviceHolder holder = (AdviceHolder)EventBus.getDefault().getStickyEvent(AdviceHolder.class);
    }
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState)
    {
        // read isTextButtonFirstClick from holder
        boolean isTextButtonFirstClick = holder.isTextButtonFirstClick();
    
        mTextButton = (Button) v.findViewById(R.id.textButton);
        mTextButton.setOnClickListener(new View.OnClickListener()
        {
            public void onClick(View v)
            {
                if (isTextButtonFirstClick)
                {
                    FragmentManager fm = getActivity().getSupportFragmentManager();
                    InputTextFragment dialog = InputTextFragment.newInstance("", isTextButtonFirstClick);
                    dialog.setTargetFragment(AdviceFragment.this, REQUEST_TEXT);
                    dialog.show(fm, DIALOG_TEXT);
    
                    // update isTextButtonFirstClick in holder
                    holder.setTextButtonFirstClick(false);
                    EventBus.getDefault().postStickyEvent(holder);
                }
                else
                {
                    FragmentManager fm = getActivity().getSupportFragmentManager();
                    InputTextFragment dialog = InputTextFragment.newInstance(mAdvice.getText(), isTextButtonFirstClick);
                    dialog.setTargetFragment(AdviceFragment.this, REQUEST_TEXT);
                    dialog.show(fm, DIALOG_TEXT);
                }
            }
        });
    ...
    }
    

    当你在某个时刻填写AdviceHolder(并将其发送到服务器或任何计划)时,将其从EventBus中删除,以便在AdviceActivity中创建新的持有者。

    EventBus.getDefault().removeStickyEvent(AdviceHolder.class);
    

    有关EventBus的其他示例,请查看http://www.stevenmarkford.com/passing-objects-between-android-activities/

    这是很多信息,希望它不会太混乱。