封装代码和UI利器—Fragment(五)

          今天要解决的问题是Fragment状态持久化,所谓Fragment状态持久化就是当窗口发生配置变化时涉及到的状态保存的问题,今天的例子就是解决窗口横竖屏切换问题。窗口在横竖屏切换的过程中是先销毁后重建的。这里的状态就是Fragment类中的成员变量的值了。

         我当时就纳闷了,既然销毁了,那怎么保存状态呢?后来我看了很多例子查阅很多资料得到了一些信息。一种就是Fragment的状态变量保存在Fragment.onSaveInstanceState方法中,同样的道理,Activity的状态变量保存在Activity.onSaveInstanceState中。另外一种就是用Fragment.setArgument方法来设置保存状态变量的Bundle对象。

Bundle  bundle = new Bundle();

bundle.putString =("name",  "ddfdd");

setArgument(bundle);

通过Fragment.getArgument()方法获取状态变量值。

     这时候有碰到问题了,就算这些值被保存下来了,但是切换横竖屏时,窗口配置变了,原来的Fragment就会被销毁,之前所做的努力不是都白费了吗?当然问题来了,当然得解决问题了,这时候需要在Activity.onSaveInstanceState方法把这个Fragment保存下来,这时候Fragment的状态变量也随之保存下来了。怎么来保存和获取呢?则是通过FragmentManager.putFragment 和FragmentManager.getFragment 分别来获取这些变量。然后就可以操作了。需要注意的在Fragment声明的成员变量需要在Framgnet.onActivityCreate方法中恢复这些状态变量。

package com.example.fragment_persistence;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.FragmentManager;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.Toast;


@SuppressLint({ "NewApi", "ShowToast" })
public class FragmentPersistenceActivity extends Activity {

	private MyFragment fragment;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_fragment_persistence);
		FragmentManager fragmentManager = getFragmentManager();
		if(fragment != null){
			fragment = (MyFragment) fragmentManager.getFragment(savedInstanceState, "fragment");
		}
		if(fragment ==null){
			fragment =(MyFragment) fragmentManager.findFragmentById(R.id.myFragment);
		}
	}


	public void onClick_SetFramentField(View view){
		if(fragment != null){
			fragment.name="name:新的字段值";
			fragment.getArguments().putString("name", "arg:新设置的值");
			Toast.makeText(this, "成功为name赋值", Toast.LENGTH_LONG).show();
		}
	}
	

	public void onClick_getfragmentFieldValue(View view){
		Toast.makeText(this, fragment.name, Toast.LENGTH_LONG).show();
		Toast.makeText(this,fragment.getArguments().getString("name"), Toast.LENGTH_LONG).show();
	}
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.fragment_persistence, menu);
		return true;
	}


	@Override
	protected void onSaveInstanceState(Bundle outState) {
		// TODO Auto-generated method stub
		if(fragment != null){
			getFragmentManager().putFragment(outState, "fragment",fragment);
		}
		super.onSaveInstanceState(outState);
	}
}

package com.example.fragment_persistence;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

@SuppressLint("NewApi")
public class MyFragment extends Fragment{

	public String name = "name:default";
	
	@Override
	public void onSaveInstanceState(Bundle outState) {
		// TODO Auto-generated method stub
		outState.putString("name", name);
		super.onSaveInstanceState(outState);
	}
	@Override
	public void onActivityCreated(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		if(savedInstanceState != null){
			String s = savedInstanceState.getString("name");
			if(s != null){
				name = s;
			}
		}
		super.onActivityCreated(savedInstanceState);
	}
	
	@Override
	public void onInflate(Activity activity, AttributeSet attrs,
			Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		
		if(getArguments() == null){
			Bundle bundle = new Bundle();
			bundle.putString("name", "arg:default");
			setArguments(bundle);
		}
		super.onInflate(activity, attrs, savedInstanceState);
	}
	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		View view = inflater.inflate(R.layout.myfragment, container, false);
		return view;
	}
}

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    
<EditText 
    android:id="@+id/editText"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    /> 

</LinearLayout>

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    
    <Button 
        android:id="@+id/button_01"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="设置Fragment中的字段"
        android:onClick="onClick_SetFramentField"
        />
      <Button 
        android:id="@+id/button_02"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="获取Fragment中的字段"
        android:onClick="onClick_getfragmentFieldValue"
        />
      <fragment 
          android:id="@+id/myFragment"
          class="com.example.fragment_persistence.MyFragment"
          android:layout_width="fill_parent"
          android:layout_height="fill_parent"
          />
</LinearLayout>




这里涉及到了三个状态,两个同为名name的字段和参数,另一个是EditText   这个控件的ID被当做键进行保存的。


封装代码和UI利器—Fragment(五)_第1张图片

这个问题也是我测试本例出现的问题,在网上查了一下原因是出现了空指针异常。

你可能感兴趣的:(封装代码和UI利器—Fragment(五))