Fragment
- API11(Android3.0)中引入了Fragment,由FragmentManager来管理。
- Fragment extends object 。
- Fragment也是Activity中的一个普通控件而已,只不过它可以像Activity一样用于显示的同时还能用来盛装其它控件,并且有类似Activity的lifecycle。
- 可被多个Acitivity重用, 在Acitivity运行中动态地移除、加入、交换等。
- 兼容API11(Android3.0)以前版本使用 v4.app.Fragment,Acitivity需要继承AppCompatActivity,通过getSupportFragmentManager() 获得v4.app.FragmentManager 。
- API11(Android3.0)以后可使用 app.Fragment,通过getFragmentManager()获得app.FragmentManager 。
生命周期lifecycle
- 类似Acitivty,但是由Activity管理,由许多不同点。
简单添加到Activity方法
private void add() {
OneFragment oneFragment = OneFragment.newInstance("");
FragmentTransaction transaction = mManager.beginTransaction();
transaction.add(R.id.fl_container, oneFragment, "one");
transaction.commit();
}
- 将Fragment添加到Activity中,并生效。
- 重要的类有FragmentManager 和FragmentTransaction,在下面详细分析。
Fragment相关的类及其方法
FragmentManager
- FragmentManager是一个抽象类, getFragmentManager()获取的是FragmentManagerImpl ,是一个实现类
//调用层级 最后是FragmentManagerImpl
getFragmentManager()
-->FragmentController(Fragment's lifecycle)
-->getFragmentManagerImpl()
-->FragmentHostCallback
-->final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
FragmentManager.java中 定义FragmentManager /FragmentManagerImpl / FragmentManagerState三个类/接口
beginTransaction() 获得FragmentTransaction,FragmentManagerImpl 中的Override的beginTransaction()
@Override
public FragmentTransaction beginTransaction() {
return new BackStackRecord(this);
}
- findFragmentById(@IdRes int id) 相同id ,取第一个找到的,一般就是最上面的。
- findFragmentByTag(String tag) 相同tag,取第一个找到的,一般就是最上面的。
- getFragments() 返回ArrayList< Fragment > mActive; 可能存在null
- 持有一个BackStackRecord的列表 ArrayList< BackStackRecord > mBackStackIndices
FragmentTransaction
add 和 replace 影响的只是界面,而控制回退的,是事务
FragmentTransaction 是一个抽象类, beginTransaction()获取的是BackStackRecord,是一个实现类
BackStackRecord extends FragmentTransaction
- add 和 replace 影响的只是界面,而控制回退的是事务,add 和 replace最后调用addOp(Op op)
addOp(Op op) 添加到队列mOps中,通过commit才会提交
void addOp(Op op) { mOps.add(op); op.enterAnim = mEnterAnim; op.exitAnim = mExitAnim; op.popEnterAnim = mPopEnterAnim; op.popExitAnim = mPopExitAnim; }
addToBackStack(将事务添加到回退栈里)
@Override public FragmentTransaction addToBackStack(String name) { if (!mAllowAddToBackStack) { throw new IllegalStateException( "This FragmentTransaction is not allowed to be added to the back stack."); } mAddToBackStack = true; mName = name; return this; }
commit (提交到处理队列里,默认不会添加到回退栈,默认等待执行),调用commitInternal(false)
int commitInternal(boolean allowStateLoss) { if (mCommitted) throw new IllegalStateException("commit already called"); if (FragmentManagerImpl.DEBUG) { Log.v(TAG, "Commit: " + this); LogWriter logw = new LogWriter(TAG); PrintWriter pw = new PrintWriter(logw); dump(" ", null, pw, null); pw.close(); } mCommitted = true; if (mAddToBackStack) { mIndex = mManager.allocBackStackIndex(this); } else { mIndex = -1; } mManager.enqueueAction(this, allowStateLoss); return mIndex; }
add
- add(@IdRes int containerViewId, Fragment fragment)
- 可能出现 Fragment already added 错误,原因:add 已经add的fragment(hashcode一样)
- lifecycle方法调用情况
10-23 17:01:58.737 13673-13673/com.wega.android E/Frag+Frame: OneFragment==null==OneFragment
10-23 17:01:58.743 13673-13673/com.wega.android E/Frag+Frame: OneFragment==0==onAttach
10-23 17:01:58.744 13673-13673/com.wega.android E/Frag+Frame: OneFragment==0==onCreate
10-23 17:01:58.744 13673-13673/com.wega.android E/Frag+Frame: OneFragment==0==onCreateView
10-23 17:01:58.753 13673-13673/com.wega.android E/Frag+Frame: OneFragment==0==onActivityCreated
10-23 17:01:58.753 13673-13673/com.wega.android E/Frag+Frame: OneFragment==0==onStart
10-23 17:01:58.753 13673-13673/com.wega.android E/Frag+Frame: OneFragment==0==onResume
- 在add 前 需要new Fragment() ,但是new不会调起Framgent生命周期动作如:oncreate ,而 Acitivty不需要我们new的,是由系统创建的.
remove
- remove(Fragment fragment)
- Remove an existing fragment
- 先获得已存在fragment才能remove 不能传空值
- 通过findFragmentById() findFragmentByTag()获得已存在fragment
- lifecycle方法调用情况
10-23 17:02:55.873 13673-13673/com.wega.android E/Frag+Frame: OneFragment==0==onPause
10-23 17:02:55.874 13673-13673/com.wega.android E/Frag+Frame: OneFragment==0==onStop
10-23 17:02:55.874 13673-13673/com.wega.android E/Frag+Frame: OneFragment==0==onDestroyView
10-23 17:02:55.874 13673-13673/com.wega.android E/Frag+Frame: OneFragment==0==onDestroy
10-23 17:02:55.874 13673-13673/com.wega.android E/Frag+Frame: OneFragment==0==onDetach
replace
- replace(@IdRes int containerViewId, Fragment fragment)
- 不能传空值
- 先remove掉相同id的所有fragment,然后在add当前的这个fragment
- add 和 remove 结合
- lifecycle方法调用情况
10-23 17:07:11.092 24280-24280/com.wega.android E/Frag+Frame: OneFragment==null==OneFragment
10-23 17:07:11.098 24280-24280/com.wega.android E/Frag+Frame: OneFragment==null==onAttach
10-23 17:07:11.098 24280-24280/com.wega.android E/Frag+Frame: OneFragment==null==onCreate
10-23 17:07:11.099 24280-24280/com.wega.android E/Frag+Frame: OneFragment==0==onPause
10-23 17:07:11.099 24280-24280/com.wega.android E/Frag+Frame: OneFragment==0==onStop
10-23 17:07:11.099 24280-24280/com.wega.android E/Frag+Frame: OneFragment==0==onDestroyView
10-23 17:07:11.099 24280-24280/com.wega.android E/Frag+Frame: OneFragment==0==onDestroy
10-23 17:07:11.099 24280-24280/com.wega.android E/Frag+Frame: OneFragment==0==onDetach
10-23 17:07:11.099 24280-24280/com.wega.android E/Frag+Frame: OneFragment==null==onCreateView
10-23 17:07:11.099 24280-24280/com.wega.android E/Frag+Frame: OneFragment==null==onActivityCreated
10-23 17:07:11.100 24280-24280/com.wega.android E/Frag+Frame: OneFragment==null==onStart
10-23 17:07:11.100 24280-24280/com.wega.android E/Frag+Frame: OneFragment==null==onResume
hide
- hide(Fragment fragment)
- 与show一起作用
- hide 已经添加的fragment 不能传空值
- hide fragment 不会调用生命周期
show
- show(Fragment fragment)
- 与hide一起作用
- This is only relevant for fragments whose views have been added to a container
- show已经hide的fragment
- show fragment 不会调用生命周期
detach
- detach(Fragment fragment)
- 与attach一起作用
- 不能传空值
- lifecycle方法调用情况
10-23 17:07:41.687 24280-24280/com.wega.android E/Frag+Frame: OneFragment==null==onPause
10-23 17:07:41.687 24280-24280/com.wega.android E/Frag+Frame: OneFragment==null==onStop
10-23 17:07:41.687 24280-24280/com.wega.android E/Frag+Frame: OneFragment==null==onDestroyView
attach
-attach(Fragment fragment)
- 与detach一起作用
- 不能传空值
- lifecycle方法调用情况
10-23 17:07:56.420 24280-24280/com.wega.android E/Frag+Frame: OneFragment==null==onCreateView
10-23 17:07:56.420 24280-24280/com.wega.android E/Frag+Frame: OneFragment==null==onActivityCreated
10-23 17:07:56.421 24280-24280/com.wega.android E/Frag+Frame: OneFragment==null==onStart
10-23 17:07:56.421 24280-24280/com.wega.android E/Frag+Frame: OneFragment==null==onResume
重建 切屏
- Fragment也有onSaveInstanceState的方法,在此方法中进行保存数据,然后在onCreate或者onCreateView或者onActivityCreated进行恢复都可以。
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putString("name", "save");
super.onSaveInstanceState(outState);
Log.e("Activity", TAG +"=="+mTag1+"=="+"onSaveInstanceState"+"=="+outState.getString("name"));
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState!=null)
{
Log.e("Activity", TAG +"=="+mTag1+"=="+"onCreate"+"=="+savedInstanceState.getString("name"));
}
Bundle arguments = getArguments();
if(arguments!=null)
{
mTag1 = arguments.getString("tag");
}
Log.e("Activity", TAG +"=="+mTag1+"=="+"onCreate");
}
demo源码
FragmentActivity
package com.wega.android.fragment;
import android.content.DialogInterface;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import com.wega.android.R;
import java.util.List;
public class FragmentActivity extends AppCompatActivity implements View.OnClickListener {
private String LOG_TAG="Frag+Frame";
private FragmentManager mManager;
private OneFragment mOneFragment;
private String TAG;
private int num;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragment);
mManager = getSupportFragmentManager();
TAG = this.getClass().getSimpleName();
if (savedInstanceState == null) {
Log.e(LOG_TAG, TAG + "==onCreate");
} else {
String name = savedInstanceState.getString("name");
Log.e(LOG_TAG, TAG + "==onCreate==name==" + name);
}
findViewById(R.id.add).setOnClickListener(this);
findViewById(R.id.remove).setOnClickListener(this);
findViewById(R.id.replace).setOnClickListener(this);
findViewById(R.id.log).setOnClickListener(this);
findViewById(R.id.show).setOnClickListener(this);
findViewById(R.id.hide).setOnClickListener(this);
findViewById(R.id.attach).setOnClickListener(this);
findViewById(R.id.detach).setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.add:
add();
break;
case R.id.remove:
remove();
break;
case R.id.replace:
replace();
break;
case R.id.show:
show();
break;
case R.id.hide:
hide();
break;
case R.id.log:
getFragmentList();
break;
case R.id.attach:
attach();
break;
case R.id.detach:
detach();
break;
}
}
private void add() {
OneFragment oneFragment = OneFragment.newInstance("" + num++);
FragmentTransaction transaction = mManager.beginTransaction();
transaction.add(R.id.fl_container, oneFragment, "one");
transaction.commit();
}
private void remove(){
Fragment fragmentById = mManager.findFragmentById(R.id.fl_container);
FragmentTransaction transaction = mManager.beginTransaction();
if(fragmentById!=null)
{
transaction.remove(fragmentById);
}
transaction.commit();
}
private void replace() {
if (mOneFragment == null) {
mOneFragment = new OneFragment();
}
FragmentTransaction transaction = mManager.beginTransaction();
transaction.replace(R.id.fl_container, mOneFragment);
transaction.commit();
}
private void show() {
Fragment fragmentById = mManager.findFragmentById(R.id.fl_container);
FragmentTransaction transaction = mManager.beginTransaction();
transaction.show(fragmentById);
transaction.commit();
}
private void hide() {
Fragment fragmentById = mManager.findFragmentById(R.id.fl_container);
FragmentTransaction transaction = mManager.beginTransaction();
transaction.hide(fragmentById);
transaction.commit();
}
private void attach() {
Fragment fragmentById = mManager.findFragmentById(R.id.fl_container);
FragmentTransaction transaction = mManager.beginTransaction();
transaction.attach(fragmentById);
transaction.commit();
}
private void detach() {
Fragment fragmentById = mManager.findFragmentById(R.id.fl_container);
FragmentTransaction transaction = mManager.beginTransaction();
transaction.detach(fragmentById);
transaction.commit();
}
private void getFragmentList() {
Fragment fragment = mManager.findFragmentById(R.id.fl_container);
Fragment fragment1 = mManager.findFragmentByTag("one");
if (fragment != null) {
Log.e("fragment", "findFragmentById=" + fragment.toString());
}
if (fragment1 != null) {
Log.e("fragments1", "findFragmentByTag=" + fragment1.toString());
}
List<Fragment> fragments = mManager.getFragments();
if (fragments == null) {
return;
}
for (int i = 0; i < fragments.size(); i++) {
if (fragments.get(i) == null) {
Log.e("fragments", "null");
} else {
Log.e("fragments", fragments.get(i).toString());
}
}
Log.e("fragments", "==========");
}
}
OneFragment
package com.wega.android.fragment;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.wega.android.R;
/**
* A simple {@link Fragment} subclass.
*/
public class OneFragment extends Fragment {
private String TAG;
private String LOG_TAG="Frag+Frame";
private String mTag1;
public OneFragment() {
TAG =this.getClass().getSimpleName();
Bundle arguments = getArguments();
if(arguments!=null)
{
mTag1 = arguments.getString("tag");
}
Log.e(LOG_TAG, TAG +"=="+mTag1+"=="+"OneFragment");
}
public static OneFragment newInstance(String tag) {
Bundle args = new Bundle();
args.putString("tag",tag);
OneFragment fragment = new OneFragment();
fragment.setArguments(args);
return fragment;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
Bundle arguments = getArguments();
if(arguments!=null)
{
mTag1 = arguments.getString("tag");
}
Log.e(LOG_TAG, TAG +"=="+mTag1+"=="+"onAttach");
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState!=null)
{
Log.e(LOG_TAG, TAG +"=="+mTag1+"=="+"onCreate"+"=="+savedInstanceState.getString("name"));
}
Bundle arguments = getArguments();
if(arguments!=null)
{
mTag1 = arguments.getString("tag");
}
Log.e(LOG_TAG, TAG +"=="+mTag1+"=="+"onCreate");
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
TAG =this.getClass().getSimpleName();
Bundle arguments = getArguments();
if(arguments!=null)
{
mTag1 = arguments.getString("tag");
}
Log.e(LOG_TAG, TAG +"=="+mTag1+"=="+"onCreateView");
View inflate = inflater.inflate(R.layout.fragment_one, container, false);
TextView viewById = (TextView) inflate.findViewById(R.id.tv_hashcode);
viewById.setText(this.toString()+"tag=="+mTag1);
return inflate;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Log.e(LOG_TAG, TAG +"=="+mTag1+"=="+"onActivityCreated");
}
@Override
public void onStart() {
super.onStart();
Log.e(LOG_TAG, TAG +"=="+mTag1+"=="+"onStart");
}
@Override
public void onResume() {
super.onResume();
Log.e(LOG_TAG, TAG +"=="+mTag1+"=="+"onResume");
}
@Override
public void onPause() {
super.onPause();
Log.e(LOG_TAG, TAG +"=="+mTag1+"=="+"onPause");
}
@Override
public void onStop() {
super.onStop();
Log.e(LOG_TAG, TAG +"=="+mTag1+"=="+"onStop");
}
@Override
public void onDestroyView() {
super.onDestroyView();
Log.e(LOG_TAG, TAG +"=="+mTag1+"=="+"onDestroyView");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.e(LOG_TAG, TAG +"=="+mTag1+"=="+"onDestroy");
}
@Override
public void onDetach() {
super.onDetach();
Log.e(LOG_TAG, TAG +"=="+mTag1+"=="+"onDetach");
}
@Override
public void onSaveInstanceState(Bundle outState) {
outState.putString("name", "save");
super.onSaveInstanceState(outState);
Log.e(LOG_TAG, TAG +"=="+mTag1+"=="+"onSaveInstanceState"+"=="+outState.getString("name"));
}
}
demo源码地址
demo源码地址:https://github.com/LinweiJ/Android
backStack
未完待续