本篇文章接上一篇Android Fragment的前世今生(一),不同的是本文将深入的分析Fragment的一些使用技巧和方法

Fragment使用进阶

常用类的解释

Fragment :主要用于定义Fragment
FragmentManager: 主要用于在Activity中操作Fragment
FragmentTransaction: 保证Fragment操作的原子性
FragmentTransaction :通过benginTransatcion()获取进而开启一个事务
transaction.add() :往Activity中添加一个Fragment
transaction.remove() :从Activity中移除一个Fragment
transaction.replace():替换Fragment,等价于remove+add
transaction.hide():隐藏当前的Fragment,
transaction.show():显示之前隐藏的Fragment
transaction.detach():解除视图状态与fragment实例的关联
transaction.attach():重建view视图,附加到UI上并显示。
transatcion.commit():提交一个事务

remove和detach的区别

在不考虑回退栈的情况下,remove会销毁整个Fragment实例,而detach则只是销毁其视图结构,实例并不会被销毁。

关于support.v4包中的fragment

在上一篇文章中,我主要使用android.app.Fragment包中的FragmentFragmentManger等,当使用android.support.v4.app.Fragment包时,必须通过getSupportFragmentManager()`来获取FragmentManger,此外v4包中提供了FragmentPagerAdapter用于支持和ViewPager的配合使用,但前者并没有提供该适配器。

在Fragment中模拟回退栈

关于这个回退栈的问题我真是够了,studio的模拟器无限卡死,主要是因为硬盘的原因,来回测试了数十次,通过back键无法实现页面回退的效果,此外,还意外发现了两个Crash,这里记录一下。

思路上很简单,我让FragmentFirst和FragmentSecond之间进行来回调用,有两种模式,一种是隐藏前一个,添加下一个(当然你可以show,为了模拟o(∩_∩)o 哈哈),第二种是直接销毁第一个并添加第二个,同时为了展示效果,我改变imageView的图片。。可惜,测试失败,于是去测试了鸿洋和郭神的Demo,依旧失败(back键直接返回home主页,我觉得应该是直接销毁了Activity),那好么我用Log好吧。请了解问题所在的朋友评论下指出问题,不胜感激,

代码:
FirstFragment

public class FirstFragment extends Fragment implements View.OnClickListener {    ImageView imageView;    private Button change;    private Button hide;    private Button destroy;    @Nullable    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {        View view = inflater.inflate(R.layout.first_layout, container, false);        //将控件绑定到View上        imageView = (ImageView) view.findViewById(R.id.imageFirst);        change = (Button) view.findViewById(R.id.imageChange);        hide = (Button) view.findViewById(R.id.hide);        destroy = (Button) view.findViewById(R.id.destroy);        change.setOnClickListener(this);        destroy.setOnClickListener(this);        hide.setOnClickListener(this);        //Log下显示BackStack元素个数        int TAG = getFragmentManager().getBackStackEntryCount();        Log.d("TAG1",String.valueOf(TAG));        if(TAG>0)            Log.d("TAG1",getFragmentManager().getBackStackEntryAt(TAG-1).toString());        return view;    }    @Override    public void onClick(View v) {        SecondFragment secondFragment = new SecondFragment();        FragmentTransaction transaction = getFragmentManager().beginTransaction();        switch (v.getId()) {            case R.id.destroy:                //保存fragment实例,移除视图与fragment实例的关联                transaction.addToBackStack(null);                transaction.replace(R.id.mainLayout, secondFragment);                break;            case R.id.imageChange:                imageView.setImageResource(R.drawable.dog);                break;            case R.id.hide:                transaction.hide(this);                transaction.addToBackStack(null);                transaction.add(R.id.mainLayout, secondFragment);                break;        }        transaction.commit();    }}

SecondFragment

public class SecondFragment extends Fragment {    FragmentTransaction transaction;    @Nullable    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {        return inflater.inflate(R.layout.second_layout, container, false);    }    //在onCreateView之后执行    @Override    public void onActivityCreated(Bundle savedInstanceState) {        super.onActivityCreated(savedInstanceState);        FirstFragment firstFragment = new FirstFragment();        transaction = getFragmentManager().beginTransaction();        transaction.hide(this);        transaction.add(R.id.mainLayout,firstFragment);        transaction.addToBackStack(null);        transaction.commit();        int TAG = getFragmentManager().getBackStackEntryCount();        Log.d("TAG2",String.valueOf(TAG));        if(TAG>0)            Log.d("TAG2",getFragmentManager().getBackStackEntryAt(TAG-1).toString());    }}

MainActivity

public class MainActivity extends AppCompatActivity {    Fragment fragmentFirst;    FragmentTransaction transaction;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        fragmentFirst = new FirstFragment();        transaction = getFragmentManager().beginTransaction();        transaction.add(R.id.mainLayout,fragmentFirst);        transaction.commit();    }    @Override    public void onBackPressed() {        super.onBackPressed();    }}

Log结果:

Log里倒是没什么问题,前两次并没有创建fragment实例,故为0,后面每次都会创建fragment实例,则依次+1.

演示图:

Fragment和Activity之间的通信

  1. 如果在Activity中包含了对应的Fragment实例,那么直接访问Fragment的属性和方法即可。

  2. 如果没有上述实例,可以通过getFragmentManager.findFragmentById()获取Fragment实例。
    Fragment fragment = getFragmentManager().findFragmentById();

  3. 在Fragment中可以通过getActivity得到当前绑定的Activity的实例,然后进行操作。

利用第三种方式实现Fragment之间的通信

测试Demo:

主要更改Frgment的代码即可,原理上就是获取FirstFragment的imageFirst引用的资源并显示到SecondFragment的imageSeocond视图上。

public class SecondFragment extends Fragment {    FragmentTransaction transaction;    private ImageView imageViewSecond;    @Nullable    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {        //绑定imageSecond到view        View view = inflater.inflate(R.layout.second_layout,container,false);        imageViewSecond = (ImageView)view.findViewById(R.id.imageSecond);        return view;    }    //在onCreateView之后执行    @Override    public void onActivityCreated(Bundle savedInstanceState) {        super.onActivityCreated(savedInstanceState);        //获取ImageFirst的图片资源        ImageView img = (ImageView) getActivity().findViewById(R.id.imageFirst);        imageViewSecond.setImageDrawable(img.getDrawable());        int TAG = getFragmentManager().getBackStackEntryCount();        Log.d("TAG2",String.valueOf(TAG));        if(TAG>0)            Log.d("TAG2",getFragmentManager().getBackStackEntryAt(TAG-1).toString());        //延迟新建FirstFragment        new Handler().postDelayed(new Runnable() {            @Override            public void run() {                FirstFragment firstFragment = new FirstFragment();                transaction = getFragmentManager().beginTransaction();                transaction.hide(SecondFragment.this);                transaction.add(R.id.mainLayout,firstFragment);                transaction.addToBackStack(null);                transaction.commit();            }        },5000);    }}

特别注意:imageSecond所显示的图片取决于回退栈栈底的那个Fragment视图的引用。所以在执行一次后不会再改变。

引入EventBus

对与Fragment的通信,通过接口回调进行封装可以使Activity和Fragment的耦合完全分离,提高开发的效率,但相对来说代码上会复杂一些,现在有更好的解决办法,那就是EventBus

关于利用EventBus进行通信我准备通过第三篇进行介绍,欢迎关注。

结合ViewPager实战

Tab实战Demo效果图:

ViewPager+pagerAdapter

特点:代码耦合度高

Fragment+FragmentManger

特点:代码简介,每个fragment单独管理一个页面,但不支持滑动

Fragment+ViewPager

全面解耦并支持滑动和点击事件

其实还可以进行很多的优化使用,后续会继续总结出来,实践代码上主要参考了郭霖和鸿洋的博客文章,有什么疑问欢迎指出。

本文源码(包括TabDemo):源码地址

更多相关文章

  1. Android(安卓)约束布局(ConstraintLayout)详解
  2. tabhost中setup()和setup(LocalActivityManager activityGroup)
  3. Android自定义视图控件
  4. android定位和地图开发实例
  5. Ripple反馈
  6. 整理 酷炫 Android、Flutter开源UI框架 其他
  7. android轻量级开源缓存框架——ASimpleCache
  8. android ViewGroup中的LayoutParams的理解和说明
  9. Android自动化测试之Monkeyrunner使用方法及实例

随机推荐

  1. android 实时麦克风变化
  2. android WebView onJsAler onJsC…
  3. Git在AndroidStudio使用的详细介绍(英文
  4. DialogFragment
  5. android 查看手机运行的进程列表
  6. android bluetooth开发基础-7管理连接
  7. Android(安卓)ActionBar 的使用
  8. 强制改变默认输入法
  9. To show image on Android
  10. android touch event summary