类似Actrivity的任务站,Activity也可以为Fragment的每一次事务维护一个回退栈。当我们将fragment的事物添加到回退栈后,当点击回退键时,将会返回到前一次添加的Fragment。当所有被添加的Fragment都被弹出后,再次点击后退键则推出当前ACTIVITY.
下面结合一个简单的例子来讲解一下Fragment的回退栈到底是怎么一会事。
这个例子里面有三个fragment,FirstFragment 、SecondFragment 、ThirdFragment,在跳转的时候我们会将前一个Fragment放入回退栈。
FirstFragment 中有一个按钮跳转到SecondFragment,还有一个checkBox, 此checkBox用来验证回退的时候是否重建UI
SecondFragment中有一个按钮跳转到ThirdFragment,还有一个EditText用来验证回退的时候是否重建UI
我们运行到手机后,首先选上checkBox,然后点击First fragment按钮 此时会切换到 SecondFragment
,我们在SecondFragment的输入框中输入一些内容例如:hello ,然后点击second fragment按钮,我们会切换到ThirdFragment,此时我们的回退栈中就有两个Fragment,此时我们按返回键此时我们有会切换回SecondFragment,并且发现其输入框中输的内容hello还在,然后在按返回键,此时我们会切换到FirstFragment,但是checkBox并未选上。这是什么原因呢?这是应为我们在切换Fragment的时候用了不同的切换方式。
从FirstFragment切换到SecondFragment,我们直接用了replace方法,此方法的实质是先remove(),再add(),remove()会将Fragment的UI视图销毁,所以在回退时,就会重新创建视图,重新调用onCreateView()方法。
而从SecondFragment切换到ThirdFragment,我们只是将SecondFragment进行了hide(),hide()只是将视图不可见,UI视图并没有销毁,所以回退时不会重走onCreateView()方法。
下面看源代码;
FirstFragment:
ample.liaoli.fragmentdemo.fragment;import android.app.Activity;import android.app.FragmentTransaction;import android.Uri;import android.os.Bundle;import android.app.Fragment;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.Button;ample.liaoli.fragmentdemo.R;public class FirstFragment extends Fragment {private SecondFragment secondFragment;public static FirstFragment newInstance(String param1, String param2) {FirstFragment fragment = new FirstFragment();return fragment;}public FirstFragment() {}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {View v = inflater.inflate(R.layout.fragment_first, container, false);Button bt = (Button) v.findViewById(R.id.bt);bt.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {secondFragment =new SecondFragment();FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();//此处实质是先remove再add,所以FirstFragment的UI视图会销毁,回退时会重新创建视图重走onCreateView方法place(R.id.fragment_layout,secondFragment,"two");//将FirstFragment放入回退栈fragmentTransaction.addToBackStack(null);fragmentTransactionmit();}});return v;}}
l
<FrameLayout xmlns:android=""xmlns:tools=""android:layout_width="match_parent"android:layout_height="match_parent"android:background="#ff5a81"tools:context=ample.liaoli.fragmentdemo.fragment.FirstFragment"><Buttonandroid:id="@+id/bt"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:text="@string/hello_blank_fragment" /><CheckBoxandroid:layout_width="wrap_content"android:layout_height="wrap_content" /></FrameLayout>
SecondFragment
ample.liaoli.fragmentdemo.fragment;import android.app.Activity; import android.app.FragmentTransaction; import android.Uri; import android.os.Bundle; import android.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button;ample.liaoli.fragmentdemo.R;public class SecondFragment extends Fragment {private ThirdFragment thirdFragment;public static SecondFragment newInstance(String param1, String param2) {SecondFragment fragment = new SecondFragment();return fragment;}public SecondFragment() {// Required empty public constructor}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {// Inflate the layout for this fragmentView v = inflater.inflate(R.layout.fragment_second, container, false);Button bt = (Button) v.findViewById(R.id.bt);bt.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();thirdFragment =new ThirdFragment();//place(R.id.fragment_layout,secondFragment);//此处是隐藏了SecondFragment,所以SecondFragment的UI视图不会销毁,只是不可见了,回退时不会重走onCreateView方法fragmentTransaction.hide(SecondFragment.this);//fragmentTransaction.add(R.id.fragment_layout,thirdFragment,"three");//将SecondFragment放入回退栈fragmentTransaction.addToBackStack(null);fragmentTransactionmit();}});return v;}}
l
<FrameLayout xmlns:android=""xmlns:tools=""android:layout_width="match_parent"android:layout_height="match_parent"android:background="#67ff79"tools:context=ample.liaoli.fragmentdemo.fragment.SecondFragment"><EditTextandroid:layout_width="match_parent"android:layout_height="wrap_content" /><Buttonandroid:id="@+id/bt"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:text="second fragment" /></FrameLayout>
ThirdFragment
ample.liaoli.fragmentdemo.fragment;import android.app.Activity; import android.app.FragmentTransaction; import android.Uri; import android.os.Bundle; import android.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.Toast;ample.liaoli.fragmentdemo.R;public class ThirdFragmentextends Fragment {public static ThirdFragmentnewInstance(String param1, String param2) {ThirdFragment fragment = new ThirdFragment();return fragment;}public ThirdFragment() {// Required empty public constructor}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {// Inflate the layout for this fragmentView v = inflater.inflate(R.layout.fragment_third, container, false);Button bt = (Button) v.findViewById(R.id.bt);bt.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Toast.makeText(getActivity(),"fragment3 is clicked ",Toast.LENGTH_SHORT).show();}});return v;}}
l
<FrameLayout xmlns:android=""xmlns:tools=""android:layout_width="match_parent"android:background="#5579ff"android:layout_height="match_parent"tools:context=ample.liaoli.fragmentdemo.fragment.ThirdFragment"><!-- TODO: Update blank fragment layout --><Buttonandroid:id="@+id/bt"android:layout_width="wrap_content"android:layout_gravity="center"android:layout_height="wrap_content"android:text="third fragment" /></FrameLayout>
FragmentBackStackActivity
ample.liaoli.fragmentdemo;import android.app.Activity; import android.app.Fragment; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem;ample.liaoli.fragmentdemo.fragment.FirstFragment;public class FragmentBackStackActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {Create(savedInstanceState);setContentView(R.layout.activity_fragment_back_stack);FragmentManager fragmentManager = getFragmentManager();FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();fragmentTransaction.add(R.id.fragment_layout,new FirstFragment(),"one");fragmentTransactionmit();}}
activity_fragment_l
<RelativeLayout xmlns:android=""xmlns:tools=""android:layout_width="match_parent"android:layout_height="match_parent"tools:context=ample.liaoli.fragmentdemo.FragmentBackStackActivity"><FrameLayoutandroid:id="@+id/fragment_layout"android:layout_width="match_parent"android:layout_height="match_parent" /></RelativeLayout>
2.fragment与Activity
fragment中可以通过getActivity()方法得到当前Activity的实例,然后通过此实例进行一系列操作。
如果Activity有Fragment的实例引用,可以同过此引用直接针对此Fragment实例进行一系列操作。
Activity中还可以通过getFragmentManager.findFragmentByTag()或者findFragmentById()获得任何Fragment实例的引用,然后通过引用去进行一系列操作
如果在Fragment中要使用Context的话,可以直接使用getActivity(),如果要求在Activity销毁后,Context还能使用的话,则可以通过getActivity().getApplicationContext()获取。
通过回调的方式进行通信,这也是比较推荐的一种方式。这种方式可以降低Activity和Fragment的耦合,同时Fragment中也不应该直接处理其他的Fragment,因为这样会耦合性会剧增,而应该都交给Fragment的维护者来处理。和接下来我们对上面的简单例子进行重构。
FirstFragment_Optimization的源码(l与上面的例子一样)
ample.liaoli.fragmentdemo.fragment;import android.app.Activity; import android.app.Fragment; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button;ample.liaoli.fragmentdemo.R;public class FirstFragment_Optimization extends Fragment implements View.OnClickListener{//回调接口public interface PerformFirstFragmentClick{void PerFormFirstFragmentClick(View view);}public static FirstFragment_Optimization newInstance(String param1, String param2) {FirstFragment_Optimization fragment = new FirstFragment_Optimization();return fragment;}public FirstFragment_Optimization() {}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {View v = inflater.inflate(R.layout.fragment_first, container, false);Button bt = (Button) v.findViewById(R.id.bt);bt.setOnClickListener(this);return v;}@Overridepublic void onClick(View v) {Activity activity = getActivity();if(activity instanceof PerformFirstFragmentClick ){((PerformFirstFragmentClick)activity).PerFormFirstFragmentClick(v);}} }
SecondFragment_Optimization (l与上面的例子一样)
ample.liaoli.fragmentdemo.fragment;import android.app.Fragment; import android.app.FragmentTransaction; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button;ample.liaoli.fragmentdemo.R;public class SecondFragment_Optimization extends Fragment implements View.OnClickListener{private ThirdFragment thirdFragment;private PerformSecondFragmentClick performSecondFragmentClick;@Overridepublic void onClick(View v) {performSecondFragmentClick.performSecondFragmentClick(v);}public interface PerformSecondFragmentClick{void performSecondFragmentClick(View view);}public void setPerformSecondFragmentClick(PerformSecondFragmentClick performSecondFragmentClick) {this.performSecondFragmentClick = performSecondFragmentClick;}public static SecondFragment_Optimization newInstance(String param1, String param2) {SecondFragment_Optimization fragment = new SecondFragment_Optimization();return fragment;}public SecondFragment_Optimization() {// Required empty public constructor}@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {// Inflate the layout for this fragmentView v = inflater.inflate(R.layout.fragment_second, container, false);Button bt = (Button) v.findViewById(R.id.bt);bt.setOnClickListener(this);return v;}}
OptimizationFragmentBackStackActivity(activity_fragment_l与上面例子一样)
ample.liaoli.fragmentdemo;import android.app.Activity; import android.app.FragmentManager; import android.app.FragmentTransaction; import android.os.Bundle; import android.view.View;ample.liaoli.fragmentdemo.fragment.FirstFragment_Optimization; ample.liaoli.fragmentdemo.fragment.SecondFragment_Optimization; ample.liaoli.fragmentdemo.fragment.ThirdFragment;public class OptimizationFragmentBackStackActivity extends Activity implements FirstFragment_Optimization.PerformFirstFragmentClick ,SecondFragment_Optimization.PerformSecondFragmentClick{private SecondFragment_Optimization secondFragment;@Overrideprotected void onCreate(Bundle savedInstanceState) {Create(savedInstanceState);setContentView(R.layout.activity_fragment_back_stack);FragmentManager fragmentManager = getFragmentManager();FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();fragmentTransaction.add(R.id.fragment_layout,new FirstFragment_Optimization(),"one");fragmentTransactionmit();}/*** FirstFragment_Optimization中的所有View的点击事件都在此处理* @param view*/@Overridepublic void PerFormFirstFragmentClick(View view) {if (secondFragment == null) {secondFragment =new SecondFragment_Optimization();secondFragment.setPerformSecondFragmentClick(this);}FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();place(R.id.fragment_layout, secondFragment, "two");fragmentTransaction.addToBackStack(null);fragmentTransactionmit();}/*** SecondFragment_Optimization中的所有View的点击事件都在此处理* @param view*/@Overridepublic void performSecondFragmentClick(View view) {FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();ThirdFragment thirdFragment = new ThirdFragment();//place(R.id.fragment_layout,secondFragment);fragmentTransaction.hide(secondFragment);fragmentTransaction.add(R.id.fragment_layout, thirdFragment, "three");fragmentTransaction.addToBackStack(null);fragmentTransactionmit();} }
可以发现FirstFragment_Optimization、 SecondFragment_Optimization不和任何Activity、Fragm耦合,可以被任意的Activity使用,
FirstFragment_Optimization中我们定义了一个借口,只要Activity实现了此接口,就可以处理FirstFragment_Optimization中的所有的Viewde 点击事件。
SecondFragment_Optimization与FirstFragment_Optimization其实是类似的,只不过多了一个
public void setPerformSecondFragmentClick(PerformSecondFragmentClick performSecondFragmentClick) {this.performSecondFragmentClick = performSecondFragmentClick; }
方法。由于多了此方法,所以在Activity中我们必须手动给我们的SecondFragment_Optimization设置一个PerformSecondFragmentClick的实例。
if (secondFragment == null) {secondFragment =new SecondFragment_Optimization();secondFragment.setPerformSecondFragmentClick(this); }
代码实现的效果与上面的例子是一模一样的,FirstFragment_Optimization和SecondFragment_Optimization中两种设置回调的方法都是可以的,并且是推荐的。我们可以根据自己的喜好来选择。
虽然Fragment可以通过getActivity()、findFragmentByTag或findFragmentById进行任何可行的操作,甚至在Fragment里面操作Fragment,但是如果没有特殊需求一般绝对不提倡。Activity担任的是Fragment的维护管理者的角色。所以应当有Activity来统一管理Fragment的操作。另外虽然Fragment不能相应Intent的打开,但是Activity可以。Activity接收Intent后,可以根据不同的参数,去决定显示哪一个Fragment。
源码下载链接: 密码: h8yp
本文发布于:2024-01-31 00:53:09,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170663369724121.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |