利用Factory模式实现Fragment切换优化

来源:互联网 发布:淘宝上哪家药店是真的 编辑:程序博客网 时间:2024/06/05 20:27

GIithub源码
准备用 Fragment 实现页面切换的效果,就去 Github 看了下别人的源码,发现他利用 Factory 模式进行了优化。下面我就把这种方法介绍给大家。

这里写图片描述

开始

下面我们就用边学边练的方式进行学习,首先打开你的 Android Studio,并新建一个 FactoryFragment 项目。

创建三个 fragment,分别是 OneFragment,TwoFragment,ThreeFragment,代码如下所示:

public class OneFragment extends Fragment {    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {        View view = inflater.inflate(R.layout.fragment_one, container, false);        ButterKnife.bind(this, view);        return view;    }}
public class ThreeFragment extends Fragment{    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {        View view = inflater.inflate(R.layout.fragment_three, container, false);        ButterKnife.bind(this, view);        return view;    }}
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {        View view = inflater.inflate(R.layout.fragment_two, container, false);        ButterKnife.bind(this, view);        return view;    }

上面的代码引入三个 fragment 布局,当我们点击相应的按钮时,会出现指定的布局, 布局文件就不再这里粘贴了,可以去上面的 Github 下载源码。

工厂类

创建工厂类 FragmentFactory,这也是我们的重点。代码如下:

public class FragmentFactory {    public static final String ONE_TAG = "one";    public static final String TWO_TAG = "two";    public static final String THREE_TAG = "three";    private OneFragment oneFragment;    private TwoFragment twoFragment;    private ThreeFragment threeFragment;    private static FragmentFactory mFactory;    private HashMap<String, Fragment> mHashMap = new HashMap<>();    private FragmentFactory() {    }    public static FragmentFactory getInstance() {        if (mFactory == null) {            synchronized (FragmentFactory.class) {                if (mFactory == null) {                    mFactory = new FragmentFactory();                }            }        }        return mFactory;    }    public Fragment getFragmentByTag(String tag) {        if (tag.equals(ONE_TAG) && oneFragment == null) {            oneFragment = new OneFragment();            mHashMap.put(ONE_TAG, oneFragment);        }        if (tag.equals(TWO_TAG) && twoFragment == null) {            twoFragment = new TwoFragment();            mHashMap.put(TWO_TAG, twoFragment);        }        if (tag.equals(THREE_TAG) && threeFragment == null) {            threeFragment = new ThreeFragment();            mHashMap.put(THREE_TAG, threeFragment);        }        return mHashMap.get(tag);    }

可以看到,我们定义了三个标记,用来判断我们点击的 fragment ,后面的代码会做详细介绍。

接着用 getInstance() 获得工厂类实例, 在这个方法里面,使用 synchronized 关键字,避免点击多次,多次创建实例,浪费资源。

获取工厂实例后,就要调用工厂类,帮我们获取每个 fragment 实例。接下来我们创建 getFragmentByTag () 方法, 用我们上面定义的标记来判断我们点击的哪个 fragment,并判断该 fragment 是否实例化,避免浪费资源。然后添加到 mHashMap 中。

最后通过 mHashMap.get() 获取点击的 fragment 实例并返回。

实现Frament切换

修改 MainActivity 中的代码,如下所示:

public class MainActivity extends AppCompatActivity implements View.OnClickListener {    @BindView(R.id.one)    RadioButton one;    @BindView(R.id.two)    RadioButton two;    @BindView(R.id.three)    RadioButton three;    private FragmentFactory mFactory;    private String mCurrentTag;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        ButterKnife.bind(this);        mFactory = FragmentFactory.getInstance();        one.setOnClickListener(this);        two.setOnClickListener(this);        three.setOnClickListener(this);        initFragment(FragmentFactory.ONE_TAG);    }    @Override    public void onClick(View v) {        switch (v.getId()){            case R.id.one:                initFragment(FragmentFactory.ONE_TAG);                break;            case R.id.two:                initFragment(FragmentFactory.TWO_TAG);                break;            case R.id.three:                initFragment(FragmentFactory.THREE_TAG);                break;        }    }    private void initFragment(String tag) {        Fragment baseFragment = mFactory.getFragmentByTag(tag);        if (baseFragment == null) {            throw new IllegalAccessError("tag is error!");        }        if (tag.equals(mCurrentTag)) {            return;        } else {            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();            if (!TextUtils.isEmpty(mCurrentTag)) {                transaction.hide(mFactory.getFragmentByTag(mCurrentTag));            }            if (!baseFragment.isAdded()) {                transaction.add(R.id.fragment_tab, baseFragment);            } else {                transaction.show(baseFragment);            }            transaction.commitAllowingStateLoss();        }        mCurrentTag = tag;    }}

首先对三个按钮创建点击事件,点击不同的按钮,显示相应的fragment,比较简单。

接下来就重点介绍下 initFragment() 方法 ,首先调用工厂类获取相应的 fragment 实例,然后创建 fragment 容器。
后面跟着 if 判断,当 mCurrentTag 不为空时, 隐藏这个 fragment (就当你点击第一次后,点击第二次的时候,就隐藏第一次的)。
当 baseFragment 没有在容器中时,transaction.add() 添加这个 fragment并显示。
当 baseFragment 在容器中时, transaction.show() 直接显示 这个 fragment.

最终程序效果在最上面,以及 Github 源码。

原创粉丝点击