一:Fragment
我们需要知道的一点:
所有的Fragment子类都必须包含一个公共的空的构造器。因为在需要的时候,Framework会经常重新实例化Fragment类,在特殊的状态恢复期间,需要能够找到这个构造器来实例化Fragment类。如果空的构造器无效,那么在状态恢复期间会导致运行时异常发生。
所以对于Fragment创建实例的传参操作,官方推荐用setArguments来传递参数,而不要使用构造函数来传参。
因为当设备参数变化时,例如竖屏变成横屏,activity会重新构建,并展示给用户。那么依附该activity的fragment也会被重新构建(反射调用Fragment的无参构造来实例化),原来的fragment的数据都会被丢失。但是通过setArguments设置的bundle参数会被保留下来。
通过setArguments来传入参数实例:
public static Fragment newInstance(String arg){
TestFragment fragment = new TestFragment();
Bundle bundle = new Bundle();
bundle.putString( ARG, arg);
fragment.setArguments(bundle);
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout. fragment_main, container, false);
TextView tv = (TextView) rootView.findViewById(R.id. tv);
tv.setText(getArguments().getString( ARG));
return rootView;
}
为了掌握Fragment的应用,我们需要了解他的完整生命周期。
->onAttach()
->onCreate()
->onCreateView()
->onActivityCreated()
->onStart()
->onResume()
->onPause()
->onStop
->onDestoryView()
->onDestory()
->onDetach()
1.当fragment被加载的时候
->onAttach()
->onCreate()
->onCreateView()
->onActivityCreated()
->onStart()
->onResume()
2.替换fragment不加入回退栈,或者退出按钮。Fragment会被销毁.
->onPause()
->onStop()
->onDestoryView()
->onDestory()
->onDetach
3.替换fragment加入回退栈,fragment实例不会被销毁,只是销毁视图而已。
->onPause()
->onStop()
->onDestoryView()
此时拿下back按键,fragment会被重新显示
->onCreateView()
->onActivityCreated()
->onStart()
->onResume()
4.Activity启动一个对话框,Activity进入onPause(),fragment也会进入onPause();
5.关闭对话框,activity进入运行状态,fragment也会进入运行状态。onPause()->onResume();fragment并没有重构视图。(当我们不想重构fragment的时候,要保存原来fragment数据的时候,可以先把fragment隐藏,hide(),处于暂停状态)
事务操作:
获取FragmentManage的方式:getFragmentManager() // v4中,getSupportFragmentManager。
transaction.remove() :
从Activity中移除一个Fragment,如果被移除的Fragment没有添加到回退栈,这个Fragment实例将会被销毁。如果添加到回退栈,则这个Fragment的实例不会销毁,但是它的布局视图会被销毁。
transaction.replace():
使用另一个Fragment替换当前的,实际上就是remove()然后add()的合体。
transaction.hide():
隐藏当前的Fragment,仅仅是设为不可见,实例并不会销毁,Fragment的布局视图也不会销毁。
transaction.show():
显示之前隐藏的Fragment。
transaction.addToBackStack(null):
添加到回退栈。
注意:常用Fragment的哥们,可能会经常遇到这样Activity状态不一致:State loss这样的错误。主要是因为:commit方法一定要在Activity.onSaveInstance()之前调用。
transaction只是记录了从一个状态到另一个状态的变化过程,即比如从FragmentA替换到FragmentB的过程,当通过函数transaction.addToBackStack(null)将这个事务添加到回退栈,则会记录这个事务的状态变化过程,如从FragmentA —>FragmentB,当用户点击手机回退键时,因为transaction的状态变化过程被保存,则可以将事务的状态变化过程还原,即将FragmentB —> FragmentA.
使用:a、比如:我在FragmentA中的EditText填了一些数据,当切换到FragmentB时,如果希望会到A还能看到数据,则适合你的就是hide和show;也就是说,希望保留用户操作的面板,你可以使用hide和show,当然了不要使劲在那new实例,进行下非null判断。
b、再比如:我不希望保留用户操作,你可以使用remove(),然后add();或者使用replace()这个和remove,add是相同的效果。
c、remove和detach有一点细微的区别,在不考虑回退栈的情况下,remove会销毁整个Fragment实例,而detach则只是销毁其视图结构,实例并不会被销毁。那么二者怎么取舍使用呢?如果你的当前Activity一直存在,那么在不希望保留用户操作的时候,你可以优先使用detach。
二:Activity
Activity生命周期
->onCreate()
->onStart()
->onResume()
->onPause()
->onStop()
->onDestory()
1.打开一个avtivity
onCreate()
->onStart()
->onResume();
2.Back键退出activity
->onPause()
->onStop
->onDestory();
3.Home键切换应用,activity并没有被销毁:
->onPause()
->onStop
4.在回到该activity:
->onRestart()
->onStart()
->onResume();
加入这个页面有edittext,里面手动输入了一些数据,当我们切换回来的时候,数据消失了
上面写的还不够直观,我们直接看图:
参考
http://www.cnblogs.com/JohnTsai/p/4052676.html
//当我们按HOME键时,我在onPause方法里,将输入的值赋给mString
@Override
protected void onPause() {
super.onPause();
mString = mEditText.getText().toString();
}
//当按HOME键时,然后再次启动应用时,我们要恢复先前状态
@Override
protected void onRestart() {
super.onRestart();
mEditText.setText(mString);
}
onCreate中的savedInstanceState有何具体作用?
在activity不可见,或者失去焦点的时候,都有可能被kill掉。这时候需要一种保存当时状态的机制。就是savedInstanceState。当activity在pause时候,被Kill之前,会调用onSaveInstanceState()来保存当时activity的状态。用来保存信息的对象bundle会传给
onCreate(Bundle savedInstanceState)和onRestoreInstanceState(Bundle savedInstanceState)两个方法。
我们可以这样重写这三个方法:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(null != savedInstanceState){
int IntTest = savedInstanceState.getInt("IntTest");
String StrTest = savedInstanceState.getString("StrTest");
}
setContentView(R.layout.main);
}
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putInt("IntTest", 0);
savedInstanceState.putString("StrTest", "savedInstanceState test");
super.onSaveInstanceState(savedInstanceState);
}
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
int IntTest = savedInstanceState.getInt("IntTest");
String StrTest = savedInstanceState.getString("StrTest");
}
那么有什么用处?
savedInstanceState状态这个参数在实现应用中有很大的用途,比如:一个游戏在退出前,保存一下当前游戏运行的状态,当下次开启时能接着上次的继续玩下去。再比如:电子书程序,当一本小说被阅读到第199页后退出了(不管是内存不足还是用户自动关闭程序),当下次打开时,读者可能已忘记了上次已阅读到第几页了,但是,读者想接着上次的读下去。如果采用saveInstallState参数,就很容易解决上述问题。